近在做一个项目,想到要使用SharedPreferences类去存储一些简单的数据,但是我们知道,使用SharedPreferences保存数据,其实质是采用了xml文件存放数据,路径为:/data/data/<package name>/shared_prefs. 但是有些时候,我们不想将xml文件存储到SharedPreferences累指定的目录下,比如说,我想将xml文件存储到sdcard下面,这个时候,我们该怎么办呢?
我们知道,SharedPreferences是封装好的类,我们只能使用类提供的方法,但是我们也知道,使用java的反射机制,类在我们面前就是透明的,我们可以任意使用类中的方法,变量,构造器等等。所以,这里,我想到使用java的反射机制去解决这个问题。但是在使用java的反射机制之前,有些概念我们还是要了解的。
Context类路径:/frameworks/base/core/java/android/content/Context.java
说明:抽象类,提供了一组通用的API。
源代码(部分)如下:
public abstract class Context {
...
public abstract Object getSystemService(String name); //获得系统级服务
public abstract void startActivity(Intent intent); //通过一个Intent启动Activity
public abstract ComponentName startService(Intent service); //启动Service
//根据文件名得到SharedPreferences对象
public abstract SharedPreferences getSharedPreferences(String name,int mode);
...
}
ContextIml.java类 路径 :/frameworks/base/core/java/android/app/ContextImpl.java
说明:该Context类的实现类为ContextIml,该类实现了Context类的功能。请注意,该函数的大部分功能都是直接调用。
其属性mPackageInfo去完成。
源代码(部分)如下:
/**
* Common implementation of Context API, which provides the base
* context object for Activity and other application components.
*/
class ContextImpl extends Context{
//所有Application程序公用一个mPackageInfo对象
/*package*/ ActivityThread.PackageInfo mPackageInfo;
@Override
public Object getSystemService(String name){
...
else if (ACTIVITY_SERVICE.equals(name)) {
return getActivityManager();
}
else if (INPUT_METHOD_SERVICE.equals(name)) {
return InputMethodManager.getInstance(this);
}
}
@Override
public void startActivity(Intent intent) {
...
//开始启动一个Activity
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null, null, intent, -1);
}
}
ContextWrapper类 路径 :\frameworks\base\core\java\android\content\ContextWrapper.java
说明: 正如其名称一样,该类只是对Context类的一种包装,该类的构造函数包含了一个真正的Context引用,即ContextIml对象。源代码(部分)如下:
public class ContextWrapper extends Context {
Context mBase; //该属性指向一个ContextIml实例,一般在创建Application、Service、Activity时赋值
//创建Application、Service、Activity,会调用该方法给mBase属性赋值
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
@Override
public void startActivity(Intent intent) {
mBase.startActivity(intent); //调用mBase实例方法
}
}
Context相关类的继承关系
SharedPreferences原则上只能保存在当前应用程序私有的Shared_prefs目录中,但利用Java的反射机制可以改变系统内定的文件存储路径。
例如:将config.xml文件保存在SD卡的根目录中。
private void savePreToSDcard() {
try {
Field field; // 获取ContextWrapper对象中的mBase变量。该变量保存了ContextImpl对象
field = ContextWrapper.class.getDeclaredField("mBase");
field.setAccessible(true);
// 获取mBase变量
Object obj = field.get(this);
// 获取ContextImpl.mPreferencesDir变量,该变量保存了数据文件的保存路径
field = obj.getClass().getDeclaredField("mPreferencesDir");
field.setAccessible(true);
// 创建自定义路径
File file = new File("/sdcard");
// 修改mPreferencesDir变量的值
field.set(obj, file);
SharedPreferences mySharedPreferences = getSharedPreferences( "config", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = mySharedPreferences.edit();
editor.putString("name", "20130310");
editor.commit();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Copyright © 2004-2024 华清远见教育科技集团 版权所有
京ICP备16055225号-5,京公海网安备11010802025203号