目录
- 1.onSaveInstanceState()方法
- 2.ViewModel
1.onSaveInstanceState()方法
当一个Activity进入了停止状态,是有可能被系统回收的。想象以下场景:应用中有一个ActivityA,用户在ActivityA的基础上启动了ActivityB,ActivityA就进入了停止状态,这个时候由于系统内存不足,将ActivityA回收掉了,然后用户按下Back键返回ActivityA,会出现什么情况呢?其实还是会正常显示ActivityA的,只不过这时并不会执行onRestart()方法,而是会执行ActivityA的onCreate()方法,因为ActivityA在这种情况下会被重新创建一次。
但是这种情况下可能会出现一个重要的问题:ActivityA中是可能存在临时数据和状态的。打个比方,MainActivity中如果有一个文本输入框,现在你输入了一段文字,然后启动NormalActivity,这时MainActivity由于系统内存不足被回收掉,过了一会你又点击了Back键回到MainActivity,这个时候你会发现刚刚输入的文字都没了,因为MainActivity被重新创建了。
如果我们的应用出现了这种情况是比较影响用户体验的,其实Activity还提供了一个onSaveInstanceState()回调方法,这个方法可以保证在Activity被回收之前一定会被调用,因此我们可以通过这个方法来解决这个问题。
onSaveInstanceState()方法会携带一个Bundle类型的参数,Bundle提供了一系列的方法保存数据,比如可以使用putString()方法保存字符串,使用putInt()方法保存整型数据,以此类推。每个保存方法需要传入两个参数,第一个参数是键,用于后面从Bundle中取值,第二个参数是真正要保存的内容。
在MainActivity中添加如下代码就可以将临时数据进行保存了:
override fun onSaveInstanceState(outState: Bundle) { | |
super.onSaveInstanceState(outState) | |
val tempData="Something you just typed" | |
outState.putString("data_key",tempData) | |
} |
数据是已经保存下来了,那么我们应该在哪里进行恢复呢?其实我们一直在使用的onCreate()方法其实也有一个Bundle类型的参数。这个参数在一般情况下都是null,但是如果在Activity被系统回收之前,你通过onSaveInstanceState()方法保存数据,这个参数就会带有之前保存的全部数据,我们只需要再通过相应的取值方法将数据取出即可。
修改MainActivity的onCreate()方法,如下所示:
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_first) | |
if(savedInstanceState!=null){ | |
val tempData = savedInstanceState.getString("data_key") | |
tempData?.let { Log.d("tag", it) } | |
} | |
} |
取出值之后就可以再做相应的恢复操作就可以了,比如将文本内容重新赋值到文本输入框上,这里我只是简单打印一下。
这里使用Bundle保存和取出数据和我们之前使用Intent传递数据的方法很类似,首先我们可以把需要传递的数据都保存在Bundle对象中,然后再将Bundle对象存放在Intent里。到了目标Activity之后,先从Intent中取出Bundle,再从Bundle中一一取出数据。
另外在手机的屏幕发生旋转的时候,Activity也会经历一个重新创建的过程,因而在这种情况下,Activity中的数据也会丢失。这种问题也可以通过onSaveInstanceState()方法来解决,但是对于横竖屏已经有了更好的方案。
2.ViewModel
使用 ViewModel,我们就无需再用这种方法保存,因为 ViewModel 会自动感知生命周期,处理数据的保存与恢复。即数据可在发生屏幕旋转等配置(其它例如分辨率调整、权限变更、系统字体样式、语言变更等)更改后继续留存。
代码如下:
package com.example.viewmodeldemo; | |
import androidx.appcompat.app.AppCompatActivity; | |
import androidx.lifecycle.ViewModelProvider; | |
import android.os.Bundle; | |
import android.util.Log; | |
import android.view.View; | |
import android.widget.Button; | |
import android.widget.TextView; | |
public class MainActivity extends AppCompatActivity { | |
private MyViewModel mMyViewModel; | |
private TextView textView; | |
private Button mButton1; | |
private Button mButton2; | |
private final String TAG="MainActivityTest"; | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
Log.d(TAG, "onCreate: "); | |
//创建一个ViewModel对象 | |
mMyViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class); | |
textView=findViewById(R.id.textView); | |
//ViewModel会保存数据,当你重新创建的时候会加载显示出来 | |
textView.setText(String.valueOf(mMyViewModel.number)); | |
mButton1=findViewById(R.id.button1); | |
mButton2=findViewById(R.id.button2); | |
mButton1.setOnClickListener(new View.OnClickListener() { | |
public void onClick(View view) { | |
mMyViewModel.number++; | |
textView.setText(String.valueOf(mMyViewModel.number)); | |
} | |
}); | |
mButton2.setOnClickListener(new View.OnClickListener() { | |
public void onClick(View view) { | |
mMyViewModel.number+=2; | |
textView.setText(String.valueOf(mMyViewModel.number)); | |
} | |
}); | |
} | |
protected void onStart() { | |
super.onStart(); | |
Log.d(TAG, "onStart: "); | |
} | |
protected void onStop() { | |
super.onStop(); | |
Log.d(TAG, "onStop: "); | |
} | |
protected void onDestroy() { | |
super.onDestroy(); | |
Log.d(TAG, "onDestroy: "); | |
} | |
protected void onPause() { | |
super.onPause(); | |
Log.d(TAG, "onPause: "); | |
} | |
protected void onResume() { | |
super.onResume(); | |
Log.d(TAG, "onResume: "); | |
} | |
} | |
package com.example.viewmodeldemo; | |
import androidx.lifecycle.ViewModel; | |
//这里的ViewModel可以看作全局变量仓库 | |
public class MyViewModel extends ViewModel { | |
public int number=0; | |
} |
这样当你旋转屏幕生命周期发生变化,你的数据还在。