activity销毁重建情况下异步任务数据保存恢复

如果acvitiy销毁时关闭异步任务,不符合常理,如果不关闭异步任务,这样可能更新已经不存在的控件,且对话框关闭dismiss空指针异常。存在这样一种需求,activity被销毁,其后台任务正在进行中,当再次进入activity时,再次显示进度,我们的目标是不对后台任务中断重启,并且对话框正常显示。

1、在fragment中声明要保存的数据。

public class FragmentDemo extends Fragment {
    private MyAsyncTask data;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /**
         * setRetainInstance(true),意味着在 Activity 重绘时,
         * 我们的 Fragment 不会被重复绘制,也就是它会被“保留”,不需要重新创建
         */
        setRetainInstance(true);
    }


    public MyAsyncTask getData() {
        return data;
    }

    public void setData(MyAsyncTask data) {
        this.data = data;
    }


}

2、以下相当于进度条:

public class LoadingDialog extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        LayoutInflater inflater = getActivity().getLayoutInflater();
        View view = inflater.inflate(R.layout.dialog_loading, null);
        Dialog dialog = new Dialog(getActivity(), R.style.dialog);
        dialog.setContentView(view);
        return dialog;
    }
}

3、异步任务:

public class MyAsyncTask extends AsyncTask {

    private SeconActivity activity;
    private LoadingDialog mLoadingDialog;
    boolean isCompleted;
    private int result;

    public MyAsyncTask(SeconActivity activity) {
        this.activity=activity;
    }

    @Override
    protected void onPreExecute() {
        mLoadingDialog = new LoadingDialog();
        mLoadingDialog.show(activity.getFragmentManager(),"LOADING");

    }

    @Override
    protected Object doInBackground(Object[] params) {

        result = loadingData();
        return null;
    }

    @Override
    protected void onPostExecute(Object o) {
        isCompleted=true;
        notifyActivityTaskCompleted();
        if (mLoadingDialog!=null){
            mLoadingDialog.dismiss();
        }
    }

    public void setActivity(SeconActivity activity){
        //如果上一个activity销毁,将与上一个acitivty绑定的DialogFragment销毁
        if (activity ==null){
            mLoadingDialog.dismiss();
        }
        //设置为当前的activity
        this.activity=activity;
        //开启一个与当前activity绑定的等待框
        if (activity!=null&& !isCompleted){
             mLoadingDialog = new LoadingDialog();
            mLoadingDialog.show(activity.getFragmentManager(),"LOADING");
        }
        //如果完成,通知activity
        if (isCompleted){
            notifyActivityTaskCompleted();
        }
    }


    private void notifyActivityTaskCompleted() {
        if (null !=activity){
            activity.onTaskComleted();
        }

    }

    private int  loadingData() {
//        int j=0;
        try {
            for (int i=0;i<50;i++){
                Thread.sleep(1000);
//                j=i;
                Log.e("mrpeng", "loadingData: "+i );
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 666;
    }

    public int getTaskResult() {
        return result;
    }
}

这个异步任务,任务开始显示一个进度条,50s后返回一个数值,并为activity提供回调,因为这里持有activity的引用,这里也提供setActivity方法,acitivity销毁时在onSaveInstanceState中设置setActivity取消之前的对话框,同时也防止了内存泄漏,activity重建时,onCreate中设置setActivity传入新的activity,再次显示加载框。这里注意,activity销毁重建并不影响加载数据,后台数据一直在加载。

4、secondActivity中实现

public class SeconActivity extends AppCompatActivity {

    private FragmentDemo fragmentDemo;
    private MyAsyncTask mMyTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e("mrpeng", "SeconActivity-=-=-=-onCreate: ");
        FragmentManager fm = getFragmentManager();
        fragmentDemo = (FragmentDemo) fm.findFragmentByTag("data");
        if (fragmentDemo==null){
            fragmentDemo=new FragmentDemo();
            fm.beginTransaction().add(fragmentDemo,"data").commit();//
        }
        mMyTask = fragmentDemo.getData();
        if (mMyTask!=null){
            mMyTask.setActivity(this);
        }else {
            mMyTask=new MyAsyncTask(this);
            mMyTask.execute();
        }
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        mMyTask.setActivity(null);
        super.onSaveInstanceState(outState);
    }

    public void onTaskComleted() {
        int taskResult = mMyTask.getTaskResult();
        Toast.makeText(this,"taskResult :::"+taskResult,Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onDestroy() {
        Log.e("mrpeng", "SeconActivity-=-=-=-onDestroy: ");
        super.onDestroy();
    }
}

如果第一次进入,则将activity传递给AsyncTask,开启任务mMyTask并把它交给fragment维护
不正常情况下,如屏幕旋转,activity设置setActvity为null,取消之前的对话框,并在activity重建时framework没有销毁,直接通过get方法去除加载任务mTask,再次显示一个新的加载框。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值