码迷,mamicode.com
首页 > 移动开发 > 详细

处女男学Android(十三)---Android 轻量级数据存储之SharedPreferences

时间:2015-01-08 22:47:57      阅读:301      评论:0      收藏:0      [点我收藏+]

标签:sharedpreferences   android数据存储   



一、前言



转载请标明出处:http://blog.csdn.net/wlwlwlwl015/article/details/42437007

初学Android的时候在Activity之间传值我都是用Intent+Bundle这种模式去实现的,刚开始觉得没什么,后来渐渐发现了弊端,就是说只能逐层传递,当我的好几个Activity都需要从一个Activity中取数据的时候,这样就显得相当局限了,传来传去的即麻烦,又不合理,后来就想在Android中有没有web开发中类似于Session的东西,只要会话没有结束,那么在多个jsp页面之间就可以任意共享数据,这样就相当方便了,查阅了相关资料,发现SharedPreferences就是我要找的东西,通过本篇blog记录一下我学习它的过程,并彻底解决以后所有项目中遇到的轻量级数据存储问题。



二、创建SharedPreferences



首先看一下官方文档中对SharedPreferences的概述:

技术分享

整体翻译一下,SharedPreferences提供了一个“允许我们去保存或者读取基本数据类型的键值对数据”的框架,你可以使用SharedPreferences去保存任意的基本数据类型的数据,例如:布尔类型、浮点型、整型、长整型以及字符串类型。在SharedPreferences中保存的数据可以"跨Seesion"保存(甚至你的application已经销毁)。


看了这段话我们大体上应该已经了解了SharedPreferences的作用了,我看完之后简单总结了以下三点:

1.SharedPreferences保存的数据格式是key-value的键值对格式,类似于Map集合。

2.SharedPreferences可保存的数据类型大体上都是基本数据类型

3.SharedPreferences中保存的数据不依赖上下文(猜也能猜出来肯定是保存在文件中了,这个后面再说)。


好了,接下来就该看看如何获取SharedPreferences对象,继续看文档,紧挨着上面一段:

技术分享

显而易见,我们有2种选择,分别是通过getSharedPreferences()getPreferences()

简单看一下,第一种是可以创建多个参数文件,并通过name属性区分(name就是你指定的第一个参数),而第二种只能为当前Activity创建一个参数文件,并且不需要指定name,因为它只能作用于当前的Activity。很明显,我们需要用第一种,因为我们需要在多个Activity之间去共享数据。那么下面就具体看一下这个方法:

package com.wl.sharedpreferencesdemo;

import com.example.sharedpreferencesdemo.R;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;

public class MainActivity extends Activity {

	private Context context;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		context = this;
		SharedPreferences sharedPreferences = context.getSharedPreferences(
				"currUserInfo", Context.MODE_PRIVATE);

	}

}

第一个参数没问题,就是我们为SharedPreferences指定的name(上面下划线标出的文档翻译),而第二个参数是一个整型的mode,具体看一下官方的APIs中的解释:

技术分享

蓝色线条标出的就是所有的MODE,所以说第二个参数我们可以选择这4种之中的任意一种,当然具体还是看需求了,下面分别解释一下官方给出的这4种MODE的适用场合。

1.MODE_PRIVATE 

Use 0 or MODE_PRIVATE for the default operation,翻译一下,使用0或者MODE_PRIVATE作为默认的操作。那就是说一般情况下我们设置这个MODE就可以了,其实这个MODE指定了该SharedPreferences数据只能被本应用程序读、写,大多数情况下我们的需求应该就是这样。

2.MODE_WORLD_READABLE

指定该SharedPreferences数据能被其它应用程序读,但不能写。在有些情况下这个权限是相当有用的,比如当一个应用需要从另一个应用中获取数据时。

3.MODE_WORLD_WRITEABLE

这个模式就是在上面的模式中追加了“可写”的权限,没有特殊需求应该不会用到这个模式。

4.MODE_MULTI_PROCESS

这个模式允许在多进程间改变相同的SharedPreferences文件,它通常用在Android 2.3及其以下的版本,所以这里就不做介绍了。

OK,了解了实例化SharedPreferences对象的方法以及参数的意思,那么就可以根据需求去实例化SharedPreferences对象了。顺带一提,getSharedPreferences()方法是以单例模式去得到对象的。



三、写入&读取数据



既然SharedPreferences是数据存储的对象,那么实例化对象之后首先应当做的就是写入数据了,至于怎么写,继续看文档,不用跳行,接着我上面贴出的那段To get...打头的往下看:

技术分享

清晰明了的三个步骤:

1.调用edit()方法去得到Editor对象。

2.通过Editor对象的putXxx方法存值。

3.调用Editor对象的commit()方法提交保存。

首先我们要明确一点,就是写入数据是通过Editor对象实现的,而Editor对象正是SharePreferences对象提供的,感觉没什么再需要说的了,下面就写一小段示例代码:

package com.wl.sharedpreferencesdemo;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity {

	private EditText etUsername;
	private EditText etPassword;
	private Button btnToOtherActy;

	private Context context;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		context = this;
		etUsername = (EditText) findViewById(R.id.et_username);
		etPassword = (EditText) findViewById(R.id.et_password);
		btnToOtherActy = (Button) findViewById(R.id.btn_to_other_acty);

		btnToOtherActy.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// 得到SharedPreferences对象
				SharedPreferences perferences = context.getSharedPreferences(
						"userInfo", Context.MODE_PRIVATE);
				// 获取EditText输入的内容
				String username = etUsername.getText().toString();
				String password = etPassword.getText().toString();
				// 得到Editor对象
				Editor editor = perferences.edit();
				// 存值
				editor.putString("username", username);
				editor.putString("password", password);
				// 提交保存
				editor.commit();
				startActivity(new Intent(MainActivity.this,
						SecondActivity.class));
			}
		});
	}

}
界面很简单,只放了2个EditText和1个Button,就不贴代码了,Activity做的事情也很简单,就是得到输入的值并保存到SharedPreferences中,可以看到最后一行跳转到了另一个Activity,其实这里我只是想在另一个Activity中去取值显示,有存必有取,从而验证是否存下了,是否能取到。顺带就贴上SecondActivity的代码看看如何取值:

package com.wl.sharedpreferencesdemo;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.TextView;

public class SecondActivity extends Activity {

	private TextView tvUsername;
	private TextView tvPassword;

	private Context context;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.second);
		context = this;
		tvUsername = (TextView) findViewById(R.id.tv_username);
		tvPassword = (TextView) findViewById(R.id.tv_password);
		SharedPreferences preferences = context.getSharedPreferences(
				"userInfo", Context.MODE_PRIVATE);
		String username = preferences.getString("username", "");
		String password = preferences.getString("password", "");
		tvUsername.setText(username);
		tvPassword.setText(password);

	}

}

很简单,直接通过SharedPreferences的getXxx方法即可根据key去获取相应的value了。现在运行一下程序,看看是否能正常取值显示:


技术分享

BINGO,看上去工作的很好,我们通过SharedPreferences成功实现了两个Activity之间的传值。



四、SharedPreferences的存储位置



之前也提到过了SharedPreferences实际是将数据存在了文件中,那么文件是什么格式,文件存在哪里呢?这些问题也是我们必须弄清楚的。程序运行之后,我们在eclipse中进入DDMS视图,切换过去之后选择“File Explorer”面板,第一次进入可能要稍等片刻,文件列表加载需要少量时间,之后我们就能看见这样的文件结构:

技术分享

需要注意的路径我已经标出来了,因为SharedPreferences的数据总是保存在

/data/data/<package name>/shared_prefs

这个路径下,进入到这个路径后我们可以发现这样一个文件:

技术分享

没错,其实就是在这个xml文件中保存了SharedPreferences的key-value键值对,而getSharedPreferences()方法的第一个参数正是这个xml文件的文件名。最后点击右上角的“Pull a file from the device”将这个xml文件pull到电脑上,并打开看一下:

技术分享

果真是通过xml文件,以key-value格式去存的数据,这也就和我们前面提到的种种猜测相吻合了。

最后需要注意一点,如果在File Explorer的根目录下的data文件夹下没有发现任何文件,或者可以点开,但看不到任何文件,那么一般应该是手机没有ROOT权限的原因,建议通过虚拟机调试即可。



五、SharedPreferences结合自定义Application的应用



在实际的项目中我们基本会结合自定义application去操作sharedpreferences,尽管sharedpreferences并不依赖上下文,但这样做还是有一定的好处和方便的,我个人认为有以下两点好处:

1.简化了数据读取的步骤。

2.提升了数据读取的性能。

比如在带有登录功能的APP中,我们一般都会在登录成功之后把用户信息存在SharedPreferences里面,下次再进入应用的时候就不必登录了。结合这个实例,我依次分析一下上面我提到的两点。


第一,简化了数据读取的步骤。

如果我们不使用application,那么在Activity中凡是需要读取数据,都要先通过当前Activity的上下文对象去获取到SharedPreferences对象,然后再通过preferences.getXxx去取值。如果我们在自定义application中定义一个用于封装用户信息的对象,在application的onCreat()方法中操作SharedPreferences读取数据并赋值给这个对象,那么在整个应用的运行过程中只需要得到application对象再取值就OK了,节省了获取SharedPreferences对象的这一行代码。


第二,提升了数据读取的性能。

如果按上面的方式去做,那么在程序运行的过程中只需要访问一次SharedPreferences,以后再取数据就可以直接从内存中的application取,而如果不用application的话,那么每次都要通过SharedPreferences访问xml文件获取数据,一个是从内存中读,一个是从文件中读,哪个快一些很明显了吧。


以上两点是我个人通过实际应用分析出来的结论,毕竟我还是新手,有些问题考虑的不一定对,不一定准确,如果有错误的地方还恳请各位批评指正。


最后就贴一段application结合sharedpreferences使用的代码。

MyApplication:

package com.wl.sess;

import com.wl.sess.model.MyConstants;
import com.wl.sess.model.UserEntity;

import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;

public class MyApplication extends Application {

	private UserEntity userEntity = new UserEntity();

	public UserEntity getUserEntity() {
		return userEntity;
	}

	public void setUserEntity(UserEntity userEntity) {
		this.userEntity = userEntity;
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		SharedPreferences sp = getSharedPreferences(MyConstants.SP_USERINFO,
				Context.MODE_PRIVATE);
		userEntity.setUserid(sp.getLong(MyConstants.SP_USERINFO_ID, -1));
		userEntity.setUsername(sp.getString(MyConstants.SP_USERINFO_USERNAME,
				""));
		userEntity.setUserpassword(sp
				.getString(MyConstants.SP_USERINFO_PWD, ""));
		userEntity.setUsertel(sp.getString(MyConstants.SP_USERINFO_TEL, ""));
		userEntity.setSessionid(sp.getString(MyConstants.SP_USERINFO_SESSIONID,
				""));
	}

}

可以看到,每次程应用启动的时候首先会从SharedPreferences中去读取数据,这样的话如果有数据,那么在其它Activity需要使用数据的时候就很方便了,直接通过application.getUserEntity.getXxx取取值就行了。一般对SharedPreferences的写入和删除都会简单封装一下,我是这样封装的:

	/**
	 * 存储用户登录信息
	 * 
	 * @param mApp
	 * @param sp
	 * @param userEnt
	 */
	public static void saveLoginUserinfo(MyApplication mApp,
			SharedPreferences sp, UserEntity userEnt) {
		Editor sped = sp.edit();
		sped.putLong(MyConstants.SP_USERINFO_ID, userEnt.getUserid());
		sped.putString(MyConstants.SP_USERINFO_USERNAME, userEnt.getUsername());
		sped.putString(MyConstants.SP_USERINFO_PWD, userEnt.getUserpassword());
		sped.putString(MyConstants.SP_USERINFO_TEL, userEnt.getUsertel());
		sped.putString(MyConstants.SP_USERINFO_SESSIONID,
				userEnt.getSessionid());
		sped.commit();

		mApp.setUserEntity(userEnt);
	}

	/**
	 * 清除用户登录信息
	 * 
	 * @param mApp
	 */
	public static void clearUserLoginInfo(MyApplication mApp) {
		SharedPreferences sp = mApp.getSharedPreferences(
				MyConstants.SP_USERINFO, Context.MODE_PRIVATE);
		Editor sped = sp.edit();
		sped.remove(MyConstants.SP_USERINFO_ID);
		sped.remove(MyConstants.SP_USERINFO_USERNAME);
		sped.remove(MyConstants.SP_USERINFO_PWD);
		sped.remove(MyConstants.SP_USERINFO_TEL);
		sped.remove(MyConstants.SP_USERINFO_SESSIONID);
		sped.commit();
	}

可以看到,写入数据之后,内存中的数据也应该保持一致。好了,到这里关于SharedPreferences的介绍就暂时告于段落,目前的使用都很简单,后续如果有更深层次的应用和理解的话会继续更新本篇blog。



六、总结



之前一直想学一下这个但总是没时间,因为SharedPreferences太常用了,比如Activity之间的数据共享和传递,或者是轻量级数据的持久化等等,第一次学有些地方可能说的不好或者不标准,欢迎各路大神批评指正,因为只有不断的改正错误才能提高,也希望自己早日脱离Android菜鸟阶段,这个点也该洗洗睡了,明天开始可能要好好总结一下hibernate优化相关的技术,有时间的话也会以blog的形式分享出来,今天就到这里,还要继续努力,加油,Raito!



处女男学Android(十三)---Android 轻量级数据存储之SharedPreferences

标签:sharedpreferences   android数据存储   

原文地址:http://blog.csdn.net/wlwlwlwl015/article/details/42437007

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!