Android RetainFragment状态保存的方法
作者:IamOkay 发布时间:2023-06-03 03:35:08
一、常见的状态保存恢复方式
①onSaveInstance + onRestoreInstance
这种方式是最通用的实现状态保存与恢复,在Android生态种,组件和View大量使用了此方式。
②android:configChanges+onConfigurationChanged
这种情况适用于屏幕旋转和配置变化,只要作用是阻止Activity重建,因此对于【语言】【时区】的调整可能需要重新启动Activity才能更新。
注意:
语言的变化需要配置为
android:configChanges="locale|layoutDirection"
屏幕旋转需要配置为
android:configChanges="orientation|keyboard|screenSize"
③onRetainNonConfigurationInstance
此方法是3.0版本的Android系统中提供了代替方式②的一种方式,使用场景是允许屏幕旋转、时区和语言调整及时反应。但是对于当前系统的状态或者进行的任务需要进行保存。
如线程任务
public class NetWorkTask extends Thread {
private volatile ProgressUpdateLinster progressUpdateLinster;
private Handler handler = new Handler(Looper.getMainLooper());
public NetWorkTask(ProgressUpdateLinster progressUpdateLinster) {
this.progressUpdateLinster = progressUpdateLinster;
}
private int progress = 0;
@Override
public void run() {
while (progress <= 100) {
if(progressUpdateLinster != null) {
handler.post(new Runnable() {
@Override
public void run() {
progressUpdateLinster.updateProgress(progress);
}
});
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
return;
}
progress += 2;
}
}
public interface ProgressUpdateLinster {
void updateProgress(int progress);
}
public void cacel() {
interrupt();
}
public void setProgressUpdateLinster(ProgressUpdateLinster progressUpdateLinster) {
this.progressUpdateLinster = progressUpdateLinster;
}
}
在Activity中保存状态
private ProgressBar progressBar;
private TextView textView;
private static final String TAG = "MainActivity";
NetWorkTask netWorkTask = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progressbar);
textView = (TextView) findViewById(R.id.tv_progroess);
if(getLastCustomNonConfigurationInstance() != null
&& getLastCustomNonConfigurationInstance() instanceof NetWorkTask) {
this.netWorkTask = (NetWorkTask) getLastCustomNonConfigurationInstance(); //获取保存的任务
this.netWorkTask.setProgressUpdateLinster(linster);
}else {
this.netWorkTask = new NetWorkTask();
netWorkTask.setProgressUpdateLinster(linster);
netWorkTask.start();
}
}
private NetWorkTask.ProgressUpdateLinster linster = new NetWorkTask.ProgressUpdateLinster() {
@Override
public void updateProgress(int progress) {
progressBar.setProgress(progress);
textView.setText(progress+"%");
Log.d(TAG,MainActivity.this.toString());
}
};
/**
* 保存任务
*/
@Override
public Object onRetainCustomNonConfigurationInstance() {
return netWorkTask;
}
④RetainFragment
所谓RetainFragment并不是多么高大上的Fragment,和DialogFragment一样本身都是比较普通的,这里的RetainFragment更注重【用途】,而非Fragment的名称。
Fragment同样是Android 3.0 版本的API,不过support-v4中也提供了补充方式。这种保存状态的原理是将Fragment加入FragmentManager的事务中,但是并不显示到界面中(也不需要实现view),因此可以成为后台Fragment。
要实现后台Fragment,必须做到在Activity重建的时候不被销毁,原理就是通过setRetainInstance方法实现。
public class WorkFragment extends Fragment {
NetWorkTask netWorkTask = null;
/**
* 重建之后这里的Context会自动替换成新的Activity
* @param context
*/
@Override
public void onAttach(Context context) {
super.onAttach(context);
//第一次启动的时候,这里network还没有初始化
//Activity重建之后,更新回调
if(netWorkTask != null) {
netWorkTask.setProgressUpdateLinster((NetWorkTask.ProgressUpdateLinster) context);
}
}
@Override
public void onDetach() {
super.onDetach();
netWorkTask.setProgressUpdateLinster(null);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //重建之后不再会调用此方法
//设置为retain instance Fragment
setRetainInstance(true);
netWorkTask = new NetWorkTask();
netWorkTask.setProgressUpdateLinster((NetWorkTask.ProgressUpdateLinster) getActivity());
netWorkTask.start();
}
}
Activity中的使用方式
public class MainActivity extends AppCompatActivity implements NetWorkTask.ProgressUpdateLinster {
private ProgressBar progressBar;
private TextView textView;
private static final String TAG = "MainActivity";
private static final String TAG_TASK_FRAGMENT = "work";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progressbar);
textView = (TextView) findViewById(R.id.tv_progroess);
//如果已经有了work fragment,那就不需要再新建了
if(getSupportFragmentManager().findFragmentByTag(TAG_TASK_FRAGMENT) == null) {
getSupportFragmentManager().beginTransaction().add(new WorkFragment(),TAG_TASK_FRAGMENT).commit();
}
}
@Override
public void updateProgress(int progress) {
progressBar.setProgress(progress);
textView.setText(progress+"%");
}
}
来源:https://my.oschina.net/ososchina/blog/1615579


猜你喜欢
- clone() 方法麻烦一些,需要将所有涉及到的类实现声明式接口 Cloneable,并覆盖Object类中的clone()方法,并设置作用
- Springboot 实体类生成数据库表JPA:springboot -jpa:数据库的一系列的定义数据持久化的标准的体系学习的目的是:利用
- 导入maven依赖<!-- https://mvnrepository.com/artifact/com.fasterxml.jack
- 在安全卫生上,经常看到有圆形的进度条在转动,效果非常好看,于是就尝试去实现一下,具体实现过程不多说了,直接上效果图,先炫耀下。效果图:分析:
- Mybatis 复杂对象resultMap数据对象含有普通属性,一对一对象,一对多对象(2种情况:单一主键和复合主键)下面是resultMa
- 在 C# WPF开发中颜色对话框控件(ColorDialog)用于对界面中的背景、文字…(拥有颜色属性的所有控件)设置
- 关于unicode和utf的关系,可以简单的记忆:Unicode是一个编码组织、一个编码规范、在java中指utf-16;utf是Unico
- 使用OptionMenu只要重写两个方法public boolean onCreateOptionsMenu(Menu menu):菜单的初
- 当我们第一次下载QQ并且打开的时候,会有一个新手引导,引导是几张图片,再加上一些文字说明,向右滑动,直到结束,今天一大早起来研究了一下关于此
- 一、为什么需要GC应用程序对资源操作,通常简单分为以下几个步骤:1、为对应的资源分配内存2、初始化内存3、使用资源4、清理资源5、释放内存应
- Spingboot JPA CriteriaBuilder获取指定字段废话不说直接贴代码public class ActivityVO im
- 一、平衡二叉树的定义平衡二叉树是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1 。它是一种高度平衡的二叉排序树。意思是说,
- 多线程编程多线程编程模式.NET 中,有三种异步编程模式,分别是基于任务的异步模式(TAP)、基于事件的异步模式(EAP)、异步编程模式(A
- 本文实例为大家分享了java实现通讯录管理系统的具体代码,供大家参考,具体内容如下完成项目的流程:1.根据需求,确定大体方向 2.功能模块分
- 在Android开发过程中,如果Android系统自带的属性不能满足我们日常开发的需求,那么就需要我们给系统控件添加额外的属性了。假如有个需
- 下面是我自己收集整理的2017年Java岗位的面试题,可以用它来好好准备面试。一、Java基础1. String类为什么是final的。2.
- C#重绘checkbox生成滑动开关,供大家参考,具体内容如下通过调用checkbox控件的paint事件,在重绘事件里判断checked属
- 一、概述应用程序配置文件,对于asp.net是 web.config,对于WINFORM程序是 App.Config(ExeName.exe
- 刚开始学习C#的时候,就听说CLR对于String类有一种特别的内存管理机制:有时候,明明声明了两个String类的对象,但是他们偏偏却指向
- 前言Camera2是Android新的Camera框架,整体来讲Camera2为应用程序提供了许多标准接口,使更多的功能可以通过参数控制;但