Android資料儲存五種方式總結
SharePreferences是用來儲存一些簡單配置資訊的一種機制,使用Map資料結構來儲存資料,以鍵值對的方式儲存,採用了XML格式將資料儲存到裝置中。例如儲存登入使用者的使用者名稱和密碼。只能在同一個包內使用,不能在不同的包之間使用,其實也就是說只能在創建它的應用中使用,其他應用無法使用。
建立的儲存檔案儲存在/data/data/<package name>/shares_prefs資料夾下。
修改和儲存資料- 根據Context的getSharedPrerences(key, [模式])方法獲取SharedPreference物件;
- 利用SharedPreference的editor()方法獲取Editor物件;
- 通過Editor的putXXX()方法,將鍵值對儲存資料;
- 通過Editor的commit()方法將資料提交到SharedPreference內。
2.檔案儲存package com.example.androidsharedpreferences; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; import android.app.Activity; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; public class MainActivity extends Activity implements OnClickListener { private EditText keyET; private EditText valueET; private Button insertBtn; private Button deleteBtn; private Button modifyBtn; private Button queryBtn; private Button clearBtn; private TextView textView; public static final String DATABASE = "text"; public static final String PATH = "/data/data/com.example.androidsharedpreferences//shared_prefs/text.xml"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); keyET = (EditText) findViewById(R.id.ed_jian); valueET = (EditText) findViewById(R.id.ed_zhi); insertBtn = (Button) findViewById(R.id.button1); deleteBtn = (Button) findViewById(R.id.button2); modifyBtn = (Button) findViewById(R.id.button3); queryBtn = (Button) findViewById(R.id.button4); clearBtn = (Button) findViewById(R.id.button5); // 用於顯示儲存檔案中資料 textView = (TextView) findViewById(R.id.tv_jiegou); insertBtn.setOnClickListener(this); deleteBtn.setOnClickListener(this); modifyBtn.setOnClickListener(this); queryBtn.setOnClickListener(this); clearBtn.setOnClickListener(this); } @Override public void onClick(View v) { // 獲取SharedPreferences物件 SharedPreferences sp = getSharedPreferences(DATABASE, Activity.MODE_PRIVATE); // 獲取Editor物件 Editor editor = sp.edit(); // 獲取介面中的資訊 String key = keyET.getText().toString(); String value = valueET.getText().toString(); switch (v.getId()) { case R.id.button1: editor.putString(key, value); editor.commit(); textView.setText(MainActivity.this.print()); break; case R.id.button2: editor.remove(key); editor.commit(); textView.setText(MainActivity.this.print()); break; case R.id.button3: editor.putString(key, value); editor.commit(); textView.setText(MainActivity.this.print()); break; case R.id.button4: String result = sp.getString(key, ""); textView.setText("key=" + key + ",value=" + result); break; case R.id.button5: editor.clear(); editor.commit(); textView.setText(MainActivity.this.print()); break; default: break; } } /** 獲取儲存檔案的資料 */ private String print() { StringBuffer buff = new StringBuffer(); BufferedReader reader= null; try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(PATH))); String str; while ((str = reader.readLine()) != null) { buff.append(str + "/n"); } } catch (Exception e) { e.printStackTrace(); } Log.d("1111111", buff.toString()); return buff.toString(); } }
在介紹檔案儲存之前我們要先了解記憶體、外部儲存、內部儲存三個概念,我們先來考慮一個問題:
開啟手機設定,選擇應用管理,選擇任意一個App,然後你會看到兩個按鈕,一個是清除快取,另一個是清除資料,那麼當我們點選清除快取的時候清除的是哪裡的資料?當我們點選清除資料的時候又是清除的哪裡的資料?讀完本文相信你會有答案。
在android開發中我們常常聽到這樣幾個概念,記憶體,內部儲存,外部儲存,很多人常常將這三個東西搞混,那麼我們今天就先來詳細說說這三個東西是怎麼回事?
記憶體,我們在英文中稱作memory,內部儲存,我們稱為InternalStorage,外部儲存我們稱為ExternalStorage,這在英文中本不會產生歧義,但是當我們翻譯為中文之後,前兩個都簡稱為記憶體,於是,混了。
那麼究竟什麼是內部儲存什麼是外部儲存呢?
首先我們開啟DDMS,有一個File Explorer,如下:
這裡有三個資料夾需要我們重視,一個是data,一個是mnt,一個是storage,我們下面就詳細說說這三個資料夾。
內部儲存
data資料夾就是我們常說的內部儲存,當我們開啟data資料夾之後(沒有root的手機不能開啟該資料夾),裡邊有兩個資料夾值得我們關注,如下:
一個資料夾是app資料夾,還有一個資料夾就是data資料夾,app資料夾裡存放著我們所有安裝的app的apk檔案,其實,當我們除錯一個app的時候,可以看到控制檯輸出的內容,有一項是uploading .....就是上傳我們的apk到這個資料夾,上傳成功之後才開始安裝。另一個重要的資料夾就是data檔案夾了,這個資料夾裡邊都是一些包名,開啟這些包名之後我們會看到這樣的一些檔案:
1.data/data/包名/shared_prefs
2.data/data/包名/databases
3.data/data/包名/files
4.data/data/包名/cache
如果開啟過data檔案,應該都知道這些資料夾是幹什麼用的,我們在使用sharedPreferenced的時候,將資料持久化儲存於本地,其實就是存在這個檔案中的xml檔案裡,我們App裡邊的資料庫檔案就儲存於databases資料夾中,還有我們的普通資料儲存在files中,快取檔案儲存在cache資料夾中,儲存在這裡的檔案我們都稱之為內部儲存。
外部儲存外部儲存才是我們平時操作最多的,外部儲存一般就是我們上面看到的storage資料夾,當然也有可能是mnt資料夾,這個不同廠家有可能不一樣。
一般來說,在storage資料夾中有一個sdcard資料夾,這個資料夾中的檔案又分為兩類,一類是公有目錄,還有一類是私有目錄,其中的公有目錄有九大類,比如DCIM、DOWNLOAD等這種系統為我們建立的資料夾,私有目錄就是Android這個資料夾,這個資料夾開啟之後裡邊有一個data資料夾,開啟這個data資料夾,裡邊有許多包名組成的資料夾。
說到這裡,我想大家應該已經可以分清楚什麼是內部儲存什麼是外部儲存了吧?好,分清楚之後我們就要看看怎麼來操作內部儲存和外部儲存了。
檔案的讀寫常用的是使用:FileOutputStream和FileInputStream下面我們來看demopackage com.example.androidfilestorage;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import android.app.Activity;
import android.content.Context;
public class MainActivity extends Activity implements OnClickListener {
private File json_file, file;
private Button btn_write, btn_read;
private EditText ed_write, ed_read;
private FileOutputStream fos;
FileInputStream inputStream;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
json_file = getFileDir(MainActivity.this, "thumb1");
if (!json_file.exists()) {
json_file.mkdirs();
}
// 建立快取json資料來源資料夾,在沒網路的情況下從這裡讀取資料
file = new File(json_file + "/txt.json");
if (!file.exists()) {
file.getParentFile().mkdirs();
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
Log.d("TestFile", "Create the file:" + file.getPath());
btn_write = (Button) findViewById(R.id.btn_inset);
btn_read = (Button) findViewById(R.id.btn_read);
ed_write = (EditText) findViewById(R.id.ed_inset);
ed_read = (EditText) findViewById(R.id.ed_read);
btn_write.setOnClickListener(this);
btn_read.setOnClickListener(this);
}
/**
* 判斷內部儲存還是外部儲存,帶SD卡使用外部儲存,不帶SD卡使用內部儲存。
*/
public File getFileDir(Context context, String uniqueName) {
String cachePath;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
cachePath = context.getExternalFilesDir(uniqueName).getPath();
} else {
cachePath = context.getFilesDir().getPath();
}
return new File(cachePath);
}
@Override
public void onClick(View v) {
String text = ed_write.getText().toString();
switch (v.getId()) {
case R.id.btn_inset:
try {
fos = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.write(text);
osw.flush();
osw.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
break;
case R.id.btn_read:
try {
inputStream = new FileInputStream(file);
byte[] bytes = new byte[1024];
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
while (inputStream.read(bytes) != -1) {
arrayOutputStream.write(bytes, 0, bytes.length);
}
inputStream.close();
arrayOutputStream.close();
String content = new String(arrayOutputStream.toByteArray());
ed_read.setText(content);
} catch (Exception e) {
}
break;
default:
break;
}
}
}
檔案的讀寫需要的許可權:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
demo下載地址:http://download.csdn.net/detail/qq_31546677/9913232
文章參考地址:
3.sqlite資料庫儲存4.ContentProvider儲存
適用範圍
對於什麼情況下才會用到自定義的ContentProvider,官方文件的Dev Guide是這樣描述的:
如果你想要提供以下的一種或幾種特性的時候你才需要構造一個ContentProvider:
- 你想要為其它的應用提供複雜的資料或者檔案;
- 你想允許使用者從你的應用中拷貝複雜的資料到其它的應用中;
- 你想要使用搜索框架來提供自定義的搜尋策略。
你完全不需要ContentProvider來呼叫一個SQLite資料庫,如果這種呼叫完全在你自己的應用之中。
也就是說,ContentProvider的作用是為別的應用呼叫本應用中的資料或者檔案提供介面,而它也是唯一的跨應用資料傳遞的介面。如果僅僅是同一個應用中的資料傳遞,則完全沒有必要使用到自定義的ContentProvider。
另一方面,雖然ContentProvider也能組織檔案資料或者SharedPreferences(其實也是檔案資料)這種資料,但大多數情況下ContentProvider是作為SQLite資料庫的呼叫介面來被繼承的。其原因大概是在於重寫的query()方法始終需要返回Cursor,而Cursor作為資料庫資料的容器,並沒有提供直接往Cursor中寫入資料的方法。
大體實現步驟1. 建立一個數據源,例如繼承SQLiteOpenHelper建立一個SQLite資料庫;
2. 建立一個繼承自ContentProvider的類,並重寫insert、delete、query、update、getType、onCreate方法,在這些方法中實現對資料來源的操作;
3. 在AndroidManifest.xml檔案中新增<provider>標籤,兩個必寫的屬性是android:name和android:authorities;
4. 在本應用或者其它應用的Activity、Service等元件中使用ContentResolver通過對應的URI來操作該自定義ContentProvider。
名詞解釋
URL
Android各種型別的URI基本上都是有固定格式的,對於ContentProvider而言,一般形如
content://com.test.cp.MyProvider/phone/1
的URI,其中:
content://是固定欄位,必需;
com.test.cp.MyProvider表示authority,是AndroidManifest.xml檔案中<provider>標籤的android:authorities屬性值,或者是遠端資料來源的主機名,必需;
phone/1表示path,是資料來源路徑,非必需,其中的phone對於資料庫來說可以視為表名,1表示的是該條資料的編號,如果沒有則一般認為是返回當前路徑(當前表)中的所有資料。
另外還可以根據自己的需要來進一步定義後續的欄位。
UriMatch物件
1. 通過new UriMatcher(UriMatcher.NO_MATCH); 例項化,常量NO_MATCH作為引數表示不匹配任何URI;
2. 例項化後呼叫addURI方法註冊URI,該方法有三個引數,分別需要傳入URI字串的authority部分、path部分以及自定義的整數code三者;
3. 在其它地方呼叫match方法匹配相應的URI,需要傳入Uri作為唯一的引數,返回上述自定義的code值。
至於其初始化的位置,如前所述,網上絕大多數示例都將其放入靜態域中例項化,原因不明。實際上放到onCreate方法中也沒什麼問題。
getType方法ContentProvider必須重寫的6個方法中,除了初始化方法onCreate以及資料操作的4個方法以外,還有一個getType方法。它的作用是根據URI返回該URI所對應的資料的MIME型別字串。這種字串的格式分為兩段:“A/B”。其中A段是固定的,集合型別(如多條資料)必須是vnd.android.cursor.dir,非集合型別(如單條資料)必須是vnd.android.cursor.item;B段可以是自定義的任意字串;A、B兩段通過“/”隔開。這個MIME型別字串的作用是要匹配AndroidManifest.xml檔案<activity>標籤下<intent-filter>標籤的子標籤<data>的屬性android:mimeType。如果不一致,則會導致對應的Activity無法啟動。
demo示例主要程式碼
package com.example.androidcustomcontentprovider;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
public class MainActivity extends Activity implements OnClickListener {
private Button btnadd, btnqueryall, btndel, btnupdate;
private EditText edtname, edtage;
private ListView lvall;
private int id;
private Uri url;
private String path="content://com.example.androidcustomcontentprovider.myprovider/person";
private List<Person> persons;
private SimpleAdapter simpleAdapter;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
List<Map<String, Object>> data = (List<Map<String, Object>>) msg.obj;
Log.d("data", "---" + data.size());
simpleAdapter = new SimpleAdapter(MainActivity.this, data, R.layout.list_item,
new String[] { "id", "name", "age" }, new int[] { R.id.tvId, R.id.tvname, R.id.tvage });
lvall.setAdapter(simpleAdapter);
simpleAdapter.notifyDataSetChanged();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
persons = new ArrayList<Person>();
btnqueryall = (Button) this.findViewById(R.id.btnqueryall);
btnadd = (Button) this.findViewById(R.id.btnadd);
edtname = (EditText) this.findViewById(R.id.edtname);
edtage = (EditText) this.findViewById(R.id.edtage);
btndel = (Button) this.findViewById(R.id.btndel);
btnupdate = (Button) this.findViewById(R.id.btnupdate);
lvall = (ListView) this.findViewById(R.id.lvall);
btnadd.setOnClickListener(this);
btnqueryall.setOnClickListener(this);
btndel.setOnClickListener(this);
btnupdate.setOnClickListener(this);
lvall.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
Log.d("position:", "" + position);
Person person = persons.get(position);
Log.d("data_onitemClick",
"id:" + person.getId() + "name:" + person.getName() + "age:" + person.getAge());
edtname.setText(person.getName());
edtage.setText("" + person.getAge());
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnadd:
ContentResolver contentResolver = MainActivity.this.getContentResolver();
url = Uri.parse(path);
ContentValues values = new ContentValues();
values.put("name", edtname.getText().toString());
values.put("age", edtage.getText().toString());
Uri result = contentResolver.insert(url, values);
Log.d("result", result.toString());
if (edtname.getText().toString().equals("") || edtage.getText().toString().equals("")) {
Toast.makeText(MainActivity.this, "輸入內容為空", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "新增成功", Toast.LENGTH_LONG).show();
getAllDate();
}
break;
case R.id.btndel:
ContentResolver contentResolver1 = MainActivity.this.getContentResolver();
url = Uri.parse(path);
Cursor cursor2 = MainActivity.this.getContentResolver().query(url, null, null, null, null);
while(cursor2.moveToNext()){
id=cursor2.getInt(cursor2.getColumnIndex("_id"));
}
Log.d("result_delete", "" + id);
// 構建Uri
String url1 = "content://com.example.androidcustomcontentprovider.myprovider/person/"
+ id;
Uri uri = Uri.parse(url1);
int result1 = contentResolver1.delete(uri, null, null);
Log.d("result_delete", "" + result1);
getAllDate();
break;
case R.id.btnupdate:
ContentResolver contentResolver11 = MainActivity.this.getContentResolver();
url = Uri.parse(path);
Cursor cursor21 = MainActivity.this.getContentResolver().query(url, null, null, null, null);
while(cursor21.moveToNext()){
id=cursor21.getInt(cursor21.getColumnIndex("_id"));
}
Log.d("result_delete", "" + id);
// 構建Uri
String url12 = "content://com.example.androidcustomcontentprovider.myprovider/person/"
+ id;
Uri uri1 = Uri.parse(url12);
ContentValues values1 = new ContentValues();
values1.put("name", edtname.getText().toString());
values1.put("age",
Integer.parseInt(edtage.getText().toString()));
int result12 = contentResolver11.update(uri1, values1, null, null);
Log.d("update result:" ,""+ result12);
System.out.println("update result:" + result12);
getAllDate();
break;
case R.id.btnqueryall:
getAllDate();
break;
default:
break;
}
}
public void getAllDate() {
persons.clear();
lvall.setAdapter(null);
url = Uri.parse(path);
Cursor cursor = MainActivity.this.getContentResolver().query(url, new String[] { "_id", "name", "age" }, null,
null, "_id");
while (cursor.moveToNext()) {
Person person = new Person();
person.setId(cursor.getInt(cursor.getColumnIndex("_id")));
person.setName(cursor.getString(cursor.getColumnIndex("name")));
person.setAge(cursor.getInt(cursor.getColumnIndex("age")));
persons.add(person);
}
cursor.close();
List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
Map<String, Object> map = null;
for (int i = 0; i < persons.size(); i++) {
map = new HashMap<String, Object>();
map.put("id", persons.get(i).getId());
map.put("name", persons.get(i).getName());
map.put("age", persons.get(i).getAge());
data.add(map);
}
if (data.size() >= persons.size()) {
}
Message msg = handler.obtainMessage();
msg.obj = data;
handler.sendMessage(msg);
}
}
demo下載地址:http://download.csdn.net/detail/qq_31546677/9913234
5.網路儲存