Android學習之路(5)——數據存儲方式

Android系統中的數據存儲區方式有五種:

五種數據存儲方式

1.文件存儲:以I/O流的形式把數據存入手機內存或SD卡,可以存儲大數據。

2.SharedPreference:本質是一個XML文件,以Map<Object,Object>形式存入手機內存中。

3.SQLite數據庫:SQLite是一個輕量級、跨平臺的數據庫。數據庫中所有信息都存儲在單一文件內,佔用內存小,並且支持SQL語法,通常用於存儲用戶信息。

4.ContentProvider:內容提供者,是Android四大組件之一,以數據庫形式存入手機內存,可以共享自己的數據給其他應用使用。

5.網絡存儲:把數據存儲到服務器,不存儲在本地,使用的時候直接從網絡獲取。

文件存儲

1.內部存儲:將應用程序中的數據以文件形式存儲到設備的內部存儲空間中,內部存儲方式存儲的文件被其所創建的應用程序私有。

內部存儲使用的是Context提供的openFileOutput()方法和openFileInput()方法,分別獲取FileOutputStream對象和FileInputStream對象。

參數name表示文件名
mode表示文件的操作模式
MODE_PRIVATE:該文件只能被當前程序讀寫,默認操作模式
MODE_APPEND:該文件可以追加內容,常用模式
MODE_WORLD_READABLE:該文件的內容可以被其他文件讀取,安全性低。
MODE_WORLD_WRITEABLE:該文件的內容可以被其他程序寫入,安全性低。

存儲數據:

String fileName="data.txt";//文件名稱
String content="helloworld";//保存數據
FileOutPutStream fos;
try{
    fos=openFileOutput(FileName,MODE_PRIVATE);
    fos.write(content.getBytes());
    fos.close();
    }catch(Exception e){
    e.printStackTrace();
    }

取出數據:

String Content="";
FileInputStream fis;
try{
    fis=openFileInput("data.txt");
    byte[] buffer=new byte[fis.available()];
    fis.read(buffer);
    content=new String(buffer);
    }catch(Exception e){
    e.printStackTrace();
    }

2.外部存儲:將文件存儲到一些外圍設備上。
由於外圍存儲設備可能被移除、丟失、或者出其他狀態,因此在使用外圍設備之前必須使用Environment.getExternalStorageState()方法來確認外圍設備是否可用。通過FileInputStream、FileOutputStream或者FileReader、FileWriter對象來讀寫外圍設備中的文件。

從外圍設備存儲數據:

String state=Environment.getEcternalStorageState();
if(state.equals(Environment.MEDIA_MOUNTED)){
    File SDPath=Environment.getExternalStorageDriectory();
    File file=new File(SDPath,"data.txt");
    String data="HelloWorld";
    FileOutputStream fos;
    try{
        fos=new FileOutputStream(file);
        fos.write(data.getBytes());
        fos.close();
        }catch(Exception e){
        e.printStackTrace();
        }

從外圍設備中讀取數據:

String state=Environment.getExternalStorageState();
if(State.equals(Environment.MEDIA_MOUNTED)){
    File SDPath=Environment.getExternalStorageDirectory();
    File file=new File(SDPath,"data.txt");
    FileInputStream fis;
    try{
        fis=new FileInputStream(file);
        BufferedReader br=new BufferedReader(new InputStreamReader(fis));
        String data=br.readLine();
        fis.close();
        }catch(Exception e){
        e.printStackTrace();
        }
    }

SharedPerferences

是Android平臺上以個輕量級的存儲類,主要用於存儲一些應用程序的配置參數。SharedPerference中存儲的數據是以key/value鍵值對的形式保存在XML文件中,該文件位於data/data/<packagename>/shared_prefs 文件夾中。需要注意的是,SharedPerferences中的value只能是float、int、long、boolean、String、StringSet類型。

使用SharedPerferences類存儲數據時,首先需要通過context.getSharedPerferences獲取SharedPerferences的實例對象。
(PS:SharedPreferences對象本身只能獲取數據,並不支持數據的存儲和修改)
數據的存儲和修改需要通過SharedPerferences.Editor()對象實現。

通過Editor對象相關方法存儲數據:

SharedPerferences sp=getSharedPerferences("data",MODE_PERIVATE);
Eidtor editor=sp.edit();// 獲取編輯器
editor.putString("name","小白");//存入String類型數據
editor.putInt("age",8);//存入Int類型數據
editor.commit();//提交修改

使用對象獲取相應的key值即可:

SharedPerferences sp=context.getSharedPreferences();
String data=sp.getString("name","");//獲取用戶名

通過該對象刪除數據:

SharedPerferences sp=context.SharedPerferences();
Editor editor=sp.edit();
editor.remove("name");//刪除一條數據
editor.clear();
editor.commit();

SQLite數據庫

SQLite遵循ACID關聯的數據庫管理系統。
ACID:原子性,一致性,隔離性,持久性。

SQLite沒有服務進程,通過文件保存數據,該文件是跨平臺。
支持NULL,INTEGER,REAL,TEXT,BLOB.
實際上SQLite也接受varchar,char,decimal等數據類型。
只不過在運算或保存時轉換成對應的五種數據類型。

1.創建SQLite數據庫

public class PersonSQLiteOpenHelper extends SQLiteOpenHelper{
    //數據庫的構建方法,用來定義數據庫的名稱,數據庫查詢的結果,數據庫的版本
    public PersonSQLiteOpenHelper(Context context){
    super(context,"person.db",null,5);
    }
    //數據庫第一次被創建時調用該方法
    public void OnCreate(SQLiteDatabase db){
    //初始化數據庫的表結構,執行一條鍵表的SQL語句
    db.execSQL("create table person(
        id integer primary key autoincrement,"+
        "name varchar(20),"+
        "number varchar(20)");
    }
    //當數據庫的版本號增加時調用
    public void onUpgrade(SQLiteDatabase db,int oldVesion, int newVersion){
    db.execSQL("alter table person  add account varchar(20);
    }
}

2.添加數據

public long add(String name,String number){
    //拿到一個讀寫的SQLiteDatabase對象
    SQLiteDatabase db=helper.getWritableDatabase();
    //將參數名和列添加到ContentValues對象裏面
    ContentValues values=new ContentValues();
    values.put("name",name);
    values.put("number",number);
    //輸入數據到person表裏
    long id=db.insert("person",null,values);
    //關閉數據庫
    db.close();
    return id;

db.execSQL(“insert into person(name ,number) value(?,?)”,new Object[]{name,number})
3.修改數據

public int update(String name,String newnumber){
    //拿到一個讀寫的SQLiteDatabase對象
    SQLiteDatabase db=helper.getWritableDatabase();
    //將參數名和列添加到ContentValues對象裏面
    ContentValues values=new ContentValues();
    //將參數以key,values
    values.put("number",newnumber);
    //輸入數據到person表裏
    int number=db.update("person",values,"name=?",new String []{name});
    //關閉數據庫
    db.close();
    return id;

4.刪除數據

public int delete(String name){
    //拿到一個讀寫的SQLiteDatabase對象
    SQLiteDatabase db=helper.getWritableDatabase();
    //刪除數據
    int number=db.delete("person","name=?",new String []{name});
    //關閉數據庫
    db.close();
    return number;

5.查詢數據

public boolean find(String name){
    //獲取一個可讀的數據庫
    SQLiteDatabase db=helper.getReadableDatabase();
    //查詢數據庫的操作  參數1:表名,參數2:查詢的列名,參數3:查詢條件
    //參數4:查詢參數值,參數5:分組條件 參數6:having條件,參數7:排列方式
    Cursor cursor=db.query("person",null,"name=?",new String[] {name},null,null,null);
    //是否有下一條值
    boolean result=cursor.moveToNext();
    //關閉遊標
    cursor.close();
    //關閉數據庫
    db.close();
    return result;
}

rawQuery()方法執行SQL語句
Cursor cursor=db.rawQuery(“select * from person where name=?”,new String []{name});

5.SQLite事務操作

PersonSQLiteOpenHelper helper =new PersonSQLiteOpenHelper(getContext());
    //獲取一個可寫的SQLiteDatabase
    SQLiteDatabase db=helper.getWritableDatabase();
    //開始數據庫的事務
    db.beginTransaction();
    try{
    //執行轉出操作
    db.execSQL("update person set account=account-1000 where name=?",new Object[]{"zhangsan"};

    //執行轉入操作
    db.execSQl("update person set account=account+1000 where name=?",new Object []{"wangwu"});
    //標記數據庫事務執行成功
    db.setTransactionSuccessful();
    }catch(Exception e){
        Log.i("事務處理失敗",e.toString());
    }finally{
        db.endTransaction();//關閉事務
        db.close();//關閉數據庫
    }
}

ContentProvider

是Android系統四大組件之一,用於保存和檢索數據,是android系統中不同應用程序之間共享數據的接口。

是不同應用程序之間進行數據交換的標準API,以Uri的形式對外提供數據,允許其他應用操作本應用數據。

1.創建內容提供者
首先定義一個類繼承android.conten包下的ContentProvider類。在使用該類時需要重寫它的onCreate()、delete()、getType()、insert()、query()、update()這幾個抽象方法。

如果指定數據的類型屬於集合型,getType()方法返回的字符串應該以“vnd.android.cursor.dir/”開頭。

如果屬於非集合類型則返回的字符串以“vnd.android.cursor.item/”.

創建者內容提供:

public class PersonDBProvider extends ContentProvider{
    public boolean onCreate(){
        return false;
    }
    public Cursor query(Uri uri,String [] projection,String selection,String [] selectionArgs,String sortOrder){
        return null;
    }
    public String getType(String uri){
        return null;
    }
    public Uri insert (Uri uri,ContentValues values){
        return null;
    }
    public int delete(Uri String selection ,String [] selectionArgs){
        return 0;
    }
    public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){
    return 0;
    }
}

註冊內容提供者:

<provider
    android:name="cn.itcast.db.PersonDBProvider"
    android:authorities="cn.itcast.db.personprovider">
</provider>

當使用provider暴露敏感的數據時,爲了數據安全,在註冊ContentProvider時,還可以爲其指定權限。
android:permission屬性:如果註冊provider時使用了該屬性,那麼其他程序在訪問ContentProvider時必須加上權限,否則會報異常。
例如:
PersonDBProvider註冊了android:permission=”mobile.permission android:name=”mobile.permission.PROVIDER”,那麼在其他應用使用該provider時需要加上權限
android:readPermission屬性:如果註冊provider時使用了該屬性,那麼其他應用程序通ContentProvider的query()方法查詢數據時,必須加上該權限。
android:writePermission屬性:如果在註冊provider時使用該屬性,那麼其他應用程序通過ContentProvider的增、刪、改這幾個方法操作數據時,必須加上權限。
(注意:在註冊provider時,爲其指定自定義權限。爲了讓自定義權限生效,首先單機清單文件中permission標籤頁的Add標籤。)

Uri

在ContentProvider的幾個抽象方法中,其中有一個參數Uri uri,它代表了數據的操作方法。
Uri時由scheme,authorites,path三部分組成。
示例:content://(scheme)cn.itcast.db.personprovider(authorities)/person(path)
shcme部分content://是一個標準前綴,表明數據被內容提供者所控制,不會被修改。
authorities部分cn.itcast.db.personprovider是在清單文件中指定的android:authorities屬性值,該值必須唯一,表示當前的內容提供者。
path部分/person代表資源,當訪問者需要不同數據時,這個部分是動態改變的。

訪問內容提供者

ContentResolver的基本用法:
通過ContentProvider暴露自己的數據,通過ContentResoler對應用程序暴露的數據進行操作。在使用ContentProvider暴露數據時提供相應的操作Uri,因此在訪問現有的ContentProvider時要指定相應的Uri,然後通過ContentResolver對象實現。

//獲取相應操作的Uri
Uri uri=Uri.parse("content://cn.itcast.db.personprovider/person");
//獲取到ContentReolve對象
ContentResolver resolve=context.getContentResolver(0;
//通過ContentResolver對象查詢數據
Cursor cursor=resolver.query(uri,new String []{"address","date","type","body"},null,null,null);
while(Cursor.moveToNext()){
    String address=cursor.getString(0);
    long date=cursor.getlong(1);
    int type=cursor.getInt(2);
    String body=cursor.getString(3);
}
cursor.close();

內容觀察者

用來觀察指定Uri所代表的的數據。當ContentObserver觀察到指定Uri所代表的數據。當ContentObserver觀察到指定Uri代表的數據發生變化時,就會觸發ContentObserver的onChange()方法。此時在onChange()方法裏用ContentResolver可以查到變化的數據。

public void ContentObserver(Handle handle//ContentObsever的派生類都需要調用該構造方法。參數可以是主線程Handle,也可以是任何Handle對象
public void onChange(boolean selfChange)
//當觀察到的Uri代表的數據發生變化時,會觸發該方法

如果使用Contentobsever觀察數據變化,就必須在ContentProvider中的delete(),insert(),update()方法中調用ContentResolver的notifyChange()方法。

//添加數據
public Uri insert(Uri uri,ContentValues values){
    if(matcher.math(uri)==INSERT){//匹配Uri路徑
    //匹配成功,返回查詢結果
    SQLiteDatabase db=helper.getWritableDatabase();
    db.insert("person",null,values);
    getContext().getContentResolver().notifyChange(PersonDao.messageuri,null);
}else{//匹配成功
    throw  new IllegalArgumentException("路徑不匹配,不能執行插入操作");
}
return null;

網絡存儲

HttpUrlConnection是Java.NET包中提供的API,我們知道Android SDK是基於Java的,所以當然優先考慮HttpUrlConnection這種最原始最基本的API,其實大多數開源的聯網框架基本上也是基於JDK的HttpUrlConnection進行的封裝罷了,掌握HttpUrlConnection需要以下幾個步驟:
1、將訪問的路徑轉換成URL。

URL url = new URL(path);

2、通過URL獲取連接。

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

3、設置請求方式。

conn.setRequestMethod(GET);

4、設置連接超時時間。

conn.setConnectTimeout(5000);

5、設置請求頭的信息。

conn.setRequestProperty(User-Agent, Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0));

 HttpClient是開源組織Apache提供的Java請求網絡框架,其最早是爲了方便Java服務器開發而誕生的,是對JDK中的HttpUrlConnection各API進行了封裝和簡化,提高了性能並且降低了調用API的繁瑣,Android因此也引進了這個聯網框架,我們再不需要導入任何jar或者類庫就可以直接使用,值得注意的是Android官方已經宣佈不建議使用HttpClient了。
HttpClient發送GET請求

1、 創建HttpClient對象

2、創建HttpGet對象,指定請求地址(帶參數)

3、使用HttpClient的execute(),方法執行HttpGet請求,得到HttpResponse對象

4、調用HttpResponse的getStatusLine().getStatusCode()方法得到響應碼

5、調用的HttpResponse的getEntity().getContent()得到輸入流,獲取服務端寫回的數據

public static String loginByHttpClientGet(String username, String password) {
        String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username=
                + username + &password= + password;
        HttpClient client = new DefaultHttpClient(); // 開啓網絡訪問客戶端
        HttpGet httpGet = new HttpGet(path); // 包裝一個GET請求
        try {
            HttpResponse response = client.execute(httpGet); // 客戶端執行請求
            int code = response.getStatusLine().getStatusCode(); // 獲取響應碼
            if (code == 200) {
                InputStream is = response.getEntity().getContent(); // 獲取實體內容
                String result = StreamTools.streamToString(is); // 字節流轉字符串
                return result;
            } else {
                return 網絡訪問失敗;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 網絡訪問失敗;
        }
    }

HttpClient發送POST請求

1,創建HttpClient對象

2,創建HttpPost對象,指定請求地址

3,創建List,用來裝載參數

4,調用HttpPost對象的setEntity()方法,裝入一個UrlEncodedFormEntity對象,攜帶之前封裝好的參數

5,使用HttpClient的execute()方法執行HttpPost請求,得到HttpResponse對象

6, 調用HttpResponse的getStatusLine().getStatusCode()方法得到響應碼

7, 調用的HttpResponse的getEntity().getContent()得到輸入流,獲取服務端寫回的數據

public static String loginByHttpClientPOST(String username, String password) {
        String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
        try {
            HttpClient client = new DefaultHttpClient(); // 建立一個客戶端
            HttpPost httpPost = new HttpPost(path); // 包裝POST請求
            // 設置發送的實體參數
            List parameters = new ArrayList();
            parameters.add(new BasicNameValuePair(username, username));
            parameters.add(new BasicNameValuePair(password, password));
            httpPost.setEntity(new UrlEncodedFormEntity(parameters, UTF-8));
            HttpResponse response = client.execute(httpPost); // 執行POST請求
            int code = response.getStatusLine().getStatusCode();
            if (code == 200) {
                InputStream is = response.getEntity().getContent();
                String result = StreamTools.streamToString(is);
                return result;
            } else {
                return 網絡訪問失敗;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 訪問網絡失敗;
        }
    }

參考:

  Android開發請求網絡方式詳解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章