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

猜你喜欢

转载自my.oschina.net/ososchina/blog/1615579