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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值