当前位置: 首页 > 编程笔记 >

Android RetainFragment状态保存的方法

符风畔
2023-03-14
本文向大家介绍Android RetainFragment状态保存的方法,包括了Android RetainFragment状态保存的方法的使用技巧和注意事项,需要的朋友参考一下

一、常见的状态保存恢复方式

①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+"%");
}
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。

 类似资料:
  • 问题内容: 我目前在tensorflow中具有一系列链接在一​​起的RNN的以下代码。我不使用MultiRNN,因为稍后我将对每个图层的输出进行处理。 目前,我有固定的时间步数。但是,我想将其更改为只有一个时间步长,但要记住批次之间的状态。因此,我需要为每个层创建一个状态变量,并将其分配给每个层的最终状态。这样的事情。 然后,对于每一层,我都需要评估sess.run函数中的保存状态以及调用训练函数

  • 我的碎片雷达有问题。 我不能保存片段的状态,然后在片段中有一个视图。每当我使用左右滑动时,都会通过覆盖扩展FragmentPagerAdapter的静态类中的getItem ( int position)方法来重新创建片段。 在方法 OnCreateView 中,每个片段实例都有几个步骤,这会导致数据库连接池饱和。 每当动态更改片段时发现的警告是:“W/SQLiteConnectionPool(1

  • 状态的保存与恢复 操作流程 为了状态的保存与恢复,我们可以先用栈上的一小段空间来把需要保存的全部通用寄存器和 CSR 寄存器保存在栈上,保存完之后在跳转到 Rust 编写的中断处理函数;而对于恢复,则直接把备份在栈上的内容写回寄存器。由于涉及到了寄存器级别的操作,我们需要用汇编来实现。 而对于如何保存在栈上,我们可以直接令 sp 栈寄存器直接减去相应需要开辟的大小,然后依次放在栈上。需要注意的是,

  • 在绘画的时候,经常会有这种情况,本来正在用绿色笔画,突然需要用红色笔画几笔,但画完了之后又要换成绿色笔。如果是在现实中作画,可以把笔蘸上不同的墨水,画了之后又蘸上之前的墨水,或者准备几只笔,要用哪只就选哪只。 在Canvas中也可以这样,不过Canvas中的画笔永远只有一只。所以,如果要更换画笔的颜色,就需要保存和恢复状态。状态其实就是画布当前属性的一个快照,包括: 图形的属性值,如strokeS

  • 问题内容: 是否有任何使用hibernate的公认的,行之有效的方式来保存实体在数据库中的更改历史? 我们需要跟踪相当多的对象,并且希望能够撤消对对象的更改。 我尝试使用hibernate模式的拦截器,但是对象的旧状态仅在执行时可用。大多数情况下我们还是这样做… 我目前正在让warp-persist和Guice一起管理会议。 问题答案: 我已经完成了一个拦截器(基于EmptyInterceptor

  • 问题 你需要保存正在运行线程的状态,这个状态对于其他的线程是不可见的。 解决方案 有时在多线程编程中,你需要只保存当前运行线程的状态。 要这么做,可使用 thread.local() 创建一个本地线程存储对象。 对这个对象的属性的保存和读取操作都只会对执行线程可见,而其他线程并不可见。 作为使用本地存储的一个有趣的实际例子, 考虑在8.3小节定义过的 LazyConnection 上下文管理器类。

  • 我的应用程序围绕一个HomeActivity,它在底部包含4个选项卡。这些选项卡中的每一个都是一个片段,所有的选项卡从一开始就被添加(而不是替换),并且在点击相应的选项卡时被隐藏/显示。 我的问题是,每当我更改tab时,我的卷轴的状态就会丢失。显示该问题的每个片段都使用(参见下面的示例)。 注意:由于某种原因,我的使用RecyclerView或ListView的片段保持了它们的滚动状态。 我读了几

  • 本文向大家介绍django session完成状态保持的方法,包括了django session完成状态保持的方法的使用技巧和注意事项,需要的朋友参考一下 本例使用登录页面演示,session的状态保持功能。 说明:因为http是无状态的,客户端请求一次页面后,就结束了,当再次访问时,服务器端并不知道浏览器此访问过什么。所以这样就需要状态保持功能,状态保存有两种方式:session和cookie都