最近在处理一个公司的老项目的时候偶然发现一个BUG,项目请求网络数据之后通过SharedPreferences保存在本地,作为数据缓存,清除的时候直接将生成的xml件删除。流程没错,但是这样做是有问题的,抽点时间写了一个小Demo,在此做个记录,权当笔记了。
先说结论:
1、getSharedPreference() 不会生成文件,这个大家都知道;
2、删除掉文件后,再次执行commit(),删除的文件会重生,重生文件的数据和删除之前的数据相同;
3、删除掉文件后,程序在没有完全退出停止运行的情况下,Preferences对象所存储的内容是不变的,虽然文件没有了,但数据依然存在;程序完全退出停止之后,数据才会丢失;
4、清除SharedPreferences数据一定要执行editor.clear(),editor.commit(),不能只是简单的删除文件,这也就是最后的结论,需要注意的地方。
好了,下面开始用一个非常简单的小Demo验证上面的结论。
1、首先是MainActivity ,只有一个Button,点击跳转,没什么东西,模拟首页,xml文件就不贴了。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.next_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this, SharedActivity.class));
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
this.finish();
}
}
2、来看SharedActivity 和对应的xml文件
public class SharedActivity extends AppCompatActivity implements View.OnClickListener{
EditText name,age,sex;
Button save,delete;
SharedPreferences preferences;
SharedPreferences.Editor editor;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shared);
name = (EditText) findViewById(R.id.name);
age = (EditText) findViewById(R.id.age);
sex = (EditText) findViewById(R.id.sex);
save = (Button) findViewById(R.id.save);
delete = (Button) findViewById(R.id.delete);
preferences = getSharedPreferences("TestCache", MODE_PRIVATE);
editor = preferences.edit();
save.setOnClickListener(this);
delete.setOnClickListener(this);
initData();
}
public void initData(){
name.setText(preferences.getString("name",""));
age.setText(preferences.getString("age",""));
sex.setText(preferences.getString("sex",""));
}
/**
* 保存SharedPreferences数据
*/
public void saveCache(){
editor.putString("name",name.getText().toString());
editor.putString("age",age.getText().toString());
editor.putString("sex",sex.getText().toString());
if(editor.commit()){
Toast.makeText(this,"保存成功!", Toast.LENGTH_SHORT).show();
}
}
/**
* 删除SharedPreferences数据文件
* @param files
*/
public void deleteCache(File[] files){
boolean flag;
for(File itemFile : files){
flag = itemFile.delete();
if (flag == false) {
deleteCache(itemFile.listFiles());
}
}
Toast.makeText(this, "清除缓存成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.save:
saveCache();
break;
case R.id.delete:
File[] files = new File("/data/data/"+this.getPackageName()+"/shared_prefs").listFiles();
deleteCache(files);
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
this.finish();
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="姓名"/>
<EditText
android:id="@+id/age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="年龄"/>
<EditText
android:id="@+id/sex"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="性别"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="20dp">
<Button
android:id="@+id/save"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:text="保存"/>
<Button
android:id="@+id/delete"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:text="删除"/>
</LinearLayout>
</LinearLayout>
布局很简单,三个输入框,两个按钮,保存代表存储数据到SharedPreferences中,删除代表删除所生成的xml文件。
Activity中的代码也很简单,都有注释,不说了,下面开始跑程序。先来验证结论 1 和 3。
1结论好验证,直接运行起来点击跳转按钮之后,到 /data/data/packageName/shared_prefs 文件夹下看一下有没有文件就行了,结果当然是没有。
3结论也好验证,程序启动之后我们将姓名、年龄、性别等要保存的信息填上之后保存,此时在 /data/data/packageName/shared_prefs 文件夹下会生成TestCache.xml文件,打开查看就是我们所保存的信息,以键值对的形式保存。然后我们再点击删除按钮,删除生成的xml文件,此时TestCache.xml文件被删除,我们点击返回键,返回到MainActivity,之后再重新跳转到SharedActivity中,我们看到我们之前保存的信息还依然存在(此时TestCache.xml文件是不存在的),反复几次都是一样;之后我们退出程序,回到手机桌面,然后在重新打开程序,发现所保存的信息还是存在,重复几次结果还是一样,最后我们在应用程序中将程序强行停止,然后重新打开程序,之前保存的信息没有了,到此,我们的3结论就验证完成。
根据上面说的,我贴几张过程图(真机演示连不上了,用的模拟器,有点卡,也没法看到文件,有兴趣的可以自己试试,需要ROOT):
上面第一张图就是验证流程,第二张为点击保存按钮后生成的文件,第三张为文件的内容,点删除时,文件被删除,也就是第二张图中的文件被删除,图就不贴了。
接下来验证 2 结论
我们在SharedActivity中的onDestroy()方法中加上两行代码:
@Override
protected void onDestroy() {
super.onDestroy();
//删除缓存数据的xml文件之后再次执行commit(),删除的文件会重生。
editor.putString("address","济南");
editor.commit();
this.finish();
}
然后重新运行程序,当我们点击删除之后(这是文件目录下是没有TestCache.xml文件的),按返回键返回到MainActivity后,我们在看一下结果:
没法用真机录制完整的动图,有兴趣的可以下载下来代码自己在手机上验证一下。
最后要说的就是结论4了,当我们要清除SharedPreferences中的数据的时候一定要先clear()、再commit(),不能直接删除xml文件,一定要注意!!!
//清空数据
editor.clear();
editor.commit();
好了,啰啰嗦嗦一大堆,最终只要记住结论4就可以了。
不说了,渴。