作者:hwj3747
转载请注明
目录
- (1)配置篇
- (2)Lambda表达式
- (3)icepick篇
- (4)butterknife篇
- (5)MVP篇
- (6)Retrofit篇
- (7)Dagger2篇
- (8)RxAndroid/RxJava篇
背景
在一个Android应用中,我们往往需要手动去保存activity或者fragment的状态,例如我们在玩一个游戏的时候,突然来了一个电话,这个时候在接听完电话之后我们返回到游戏中,这个时候我们希望游戏还是之前那个进度,那么我们就需要将其状态保存起来,这样在其被摧毁时,我们还能够根据保存的状态回到之前的进度。
举个例子
public class MainActivity extends AppCompatActivity {
TextView text;//
int mCodeData=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text=(TextView)findViewById(R.id.text);
Button button=(Button)findViewById(R.id.add);
text.setText(mCodeData + "");
button.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
mCodeData++;
text.setText(mCodeData+"");
}
}); }
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
这个小程序实现的是一个很简单的功能,界面上有一个add按钮和一个textview用来计数,每按一次add,textView显示+1.如下图我们把它加到11。
![](https://img.haomeiwen.com/i2638634/24d957652336a0f8.png)
然后翻转屏幕,发现又变回0了,这是因为翻转屏幕的时候activity被摧毁了,但是我们的mCodeData这个变量并没有保存起来,导致重新加载的时候又初始化为0了。这里要注意的是系统会为XML文件的具有id的view自动保存状态。这里因为我们在OnCreate方法里初始化了textView,所以翻转屏幕后又重新设置了textview的值为0.
![](https://img.haomeiwen.com/i2638634/1d1c19cc66956e97.png)
一般性的解决办法
通常遇到这种情况,我们就需要为系统保存mCodeData这个变量,这样销毁后再重建也能恢复之前的状态。具体这样做:
public class MainActivity extends AppCompatActivity {
TextView text;//
int mCodeData=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState!=null)
mCodeData=savedInstanceState.getInt("code");
text=(TextView)findViewById(R.id.text);
Button button=(Button)findViewById(R.id.add);
text.setText(mCodeData + "");
button.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
mCodeData++;
text.setText(mCodeData+"");
}
}); }
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt("code",mCodeData);
super.onSaveInstanceState(outState);
}
在onSaveInstanceState方法里用outState保存mCodeData的值,然后在OnCreate方法里用savedInstanceState恢复mCodeData的值。这里可能有人会有疑问了,不是还有onRestoreInstanceState
这个方法吗,为什么不在这个方法里做状态恢复呢。其实我们要注意的是,onRestoreInstanceState这个方法的执行是在OnStart和onResume方法之间的,所以在OnCreate方法里,还没有执行到这个方法,但是我们是在OnCreate里面做初始化的,所以状态恢复要写到OnCreate方法里面。这样,我们翻转屏幕得到:
![](https://img.haomeiwen.com/i2638634/c6ef50ade3029708.png)
可以看到翻转屏幕,不会重置为0了,这样,我们的目的就达到了。但是,这真的是一个很好的解决方案吗,试想一下,如果我有很多类似例子中的mCodeData这样的成员变量需要保存,那么我是不是要写很长的代码去保存这些数据,再写很长的代码去恢复这些数据。显然,这样是极其麻烦的。
icepick
为了解决上面的问题,icepick出现了,它使用了一种很方便的方式去保存和恢复这些状态,即注解的方式,比如上面的例子,我们只需要这样做:
public class MainActivity extends AppCompatActivity {
TextView text;//
@State
int mCodeData=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Icepick.restoreInstanceState(this, savedInstanceState);
text=(TextView)findViewById(R.id.text);
Button button=(Button)findViewById(R.id.add);
text.setText(mCodeData + "");
button.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
mCodeData++;
text.setText(mCodeData+"");
}
}); }
@Override
protected void onSaveInstanceState(Bundle outState) {
Icepick.saveInstanceState(this, outState);
super.onSaveInstanceState(outState);
}
在需要保存和恢复状态的变量前加上@state注解,在onSaveInstanceState方法加上Icepick.saveInstanceState(this, outState);
这一句保存状态,在需要恢复状态的地方加上Icepick.restoreInstanceState(this, savedInstanceState);
这一句恢复状态。这样就大功告成了,再也不用再去写put,get这些繁琐的方法了!
网友评论