Android數據存儲五種方式總結

1.Android中的SharedPreferences存儲數據方式

SharePreferences是用來存儲一些簡單配置信息的一種機制,使用Map數據結構來存儲數據,以鍵值對的方式存儲,採用了XML格式將數據存儲到設備中。例如保存登錄用戶的用戶名和密碼。只能在同一個包內使用,不能在不同的包之間使用,其實也就是說只能在創建它的應用中使用,其他應用無法使用。

創建的存儲文件保存在/data/data/<package name>/shares_prefs文件夾下。

修改和存儲數據
  • 根據Context的getSharedPrerences(key, [模式])方法獲取SharedPreference對象;
  • 利用SharedPreference的editor()方法獲取Editor對象;
  • 通過Editor的putXXX()方法,將鍵值對存儲數據;
  • 通過Editor的commit()方法將數據提交到SharedPreference內。
demo示例:

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();
	}
}

demo下載地址:http://download.csdn.net/detail/qq_31546677/9913230

文章參考地址:http://blog.csdn.net/zuolongsnail/article/details/6556703

2.文件存儲

在介紹文件存儲之前我們要先了解內存、外部存儲、內部存儲三個概念,我們先來考慮一個問題:

打開手機設置,選擇應用管理,選擇任意一個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下面我們來看demo

package 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

文章參考地址:

內部存儲和外部存儲理解:http://www.cnblogs.com/jingmo0319/p/5586559.html

3.sqlite數據庫存儲

sqlite以前介紹過了在這裏就不介紹了需要的參考我的博客:http://blog.csdn.net/qq_31546677/article/details/68486012

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

文章參考地址:http://www.cnblogs.com/wangfeng520/p/5099465.html

http://blog.csdn.net/zuolongsnail/article/details/6566317

http://blog.csdn.net/worker90/article/details/7016430

http://blog.csdn.net/amazing7/article/details/51324022

5.網絡存儲

網絡操作博主已經講過了,可以參考博主的這一篇文章基本沒問題:http://blog.csdn.net/qq_31546677/article/details/58603185

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