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

标签:Android,RetainFragment
0
投稿

猜你喜欢

  • Android实现自定义圆形进度条

    2022-10-28 04:55:22
  • IntelliJ IDEA修改新建文件自动生成注释的user名

    2021-12-29 04:27:38
  • Android实现自由拖动并显示文字的悬浮框

    2023-06-08 06:30:39
  • Android webview与js交换JSON对象数据示例

    2022-10-19 18:36:18
  • Intellij Idea中进行Mybatis逆向工程的实现

    2021-06-05 00:08:53
  • Java中二维数组的正确使用方法介绍

    2023-11-19 16:14:18
  • Android开发之Android.mk模板的实例详解

    2022-02-20 09:11:44
  • java通过Jsoup爬取网页过程详解

    2021-12-20 03:24:10
  • 深入理解ThreadLocal工作原理及使用示例

    2022-02-27 19:24:14
  • C++之try catch 异常处理入门实例

    2021-09-13 04:42:07
  • Spring JPA find单表查询方法示例详解

    2022-11-03 19:43:38
  • Java线程中sleep和wait的区别详细介绍

    2021-08-27 02:23:12
  • 解决SpringBoot 测试类无法自动注入@Autowired的问题

    2023-11-02 04:34:14
  • Springboot jar主清单属性丢失解决方案

    2022-04-06 05:30:26
  • Android开发使用Message对象分发必备知识点详解

    2022-02-08 21:32:49
  • Java编程技巧:if-else优化实践总结归纳

    2022-04-14 09:04:20
  • Eclipse 2020-06 汉化包安装步骤详解(附汉化包+安装教程)

    2021-05-31 09:26:37
  • 浅谈Java 三种方式实现接口校验

    2023-01-20 02:57:55
  • SpringMVC 参数绑定之视图传参到控制器的实现代码

    2021-12-29 11:54:17
  • java对ArrayList排序代码示例

    2023-11-24 20:14:21
  • asp之家 软件编程 m.aspxhome.com