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開發請求網絡方式詳解。