1.Android中的SharedPreferences存儲數據方式
SharePreferences是用來存儲一些簡單配置信息的一種機制,使用Map數據結構來存儲數據,以鍵值對的方式存儲,採用了XML格式將數據存儲到設備中。例如保存登錄用戶的用戶名和密碼。只能在同一個包內使用,不能在不同的包之間使用,其實也就是說只能在創建它的應用中使用,其他應用無法使用。
創建的存儲文件保存在/data/data/<package name>/shares_prefs文件夾下。
- 根據Context的getSharedPrerences(key, [模式])方法獲取SharedPreference對象;
- 利用SharedPreference的editor()方法獲取Editor對象;
- 通過Editor的putXXX()方法,將鍵值對存儲數據;
- 通過Editor的commit()方法將數據提交到SharedPreference內。
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下面我們來看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
文章參考地址:
內部存儲和外部存儲理解: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