如何在onPostExecute(UI Blocking Task)运行时允许设备旋转

时间:2016-02-29 12:35:27

标签: java android android-asynctask onconfigurationchanged

我是Android新手,但基于我的理解,onPostExecute必须在主UI线程上运行才能访问视图等等,这会阻止UI直到完成。但该应用程序看起来很丑 - 如果它崩溃 - 当我在onPostExecute运行时尝试旋转设备时(我知道它应该是一个轻量级的任务但我记得慢速手机所以这可能实际上发生在我的HBO中)

现在,这是我的代码,我知道我相信我应该在我的Task,Fragment和Activity之间使用接口进行通信,但它现在只是一个概念证明。

//MovieTask Class
public class MovieTask extends AsyncTask<Void, Void, String> {


    private Activity activity;

    public MovieTask(Activity activity) {
        onAttach(activity);
    }

    //should be an interface
    public void onAttach(Activity activit) {
        this.activity = activit;
    }

    //should be an interface
    public void onDetach() {
        this.activity = null;
    }

    @Override
    protected String doInBackground(Void... params) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        Log.e("ASYNC TASK", "DONE");
        return "DONE: FROM DO TO POST";
    }

    @Override
    protected void onPostExecute(String s) {

        if(this.activity != null)
        {
            ((MainActivity) activity).ShowResult(s);
            Log.e("MovieTask", "Result Received");

        }else
            Log.e("MovieTask", "Activity is null (1)");
    }
}

//My Non-UI Fragment to decouple the Task from the Activity
public class NonUIFragment extends Fragment {

    private MovieTask myTask;
    private Activity activity;



    public NonUIFragment() {
        // Required empty public constructor
    }

    public void BeginTask() {


        if (activity != null) {
            myTask = new MovieTask(activity);
            myTask.execute();
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        //check that the passed context is an Activity first then,
        if (context instanceof Activity) {
            this.activity = (Activity) context;

            if(myTask != null) {
                myTask.onAttach((Activity) context);
            }
        }
    }


    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
setRetainInstance
        setRetainInstance(true);
    }

    @Override
    public void onDetach() {
        super.onDetach();

        if(myTask != null) {
            myTask.onDetach();
    }
}

//Main Activity (Task Consumer)
public class MainActivity extends AppCompatActivity {

    NonUIFragment nonUIFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            nonUIFragment = new NonUIFragment();
            getSupportFragmentManager()
                    .beginTransaction()
                    .add(nonUIFragment, "nonUIFragment")
                    .commit();
        }
        else
        {
            nonUIFragment = (NonUIFragment) getSupportFragmentManager().findFragmentByTag("nonUIFragment");
        }

        Button btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                nonUIFragment.BeginTask();
            }
        });
    }


    //should be the consumer interface
    public void ShowResult(String result)
    {
        try {
            Thread.sleep(5000);
            TextView txtVw = (TextView) findViewById(R.id.txtVw);
            txtVw.setText(result);

        } catch (InterruptedException e) {
            Log.e("MovieTask", "mCallbacks is null (2)");

        }
    }


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        TextView txtVw = (TextView) findViewById(R.id.txtVw);
        String result = txtVw.getText().toString();

        outState.putString("result", result);
    }

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

        String result = savedInstanceState.getString("result");

        TextView txtVw = (TextView) findViewById(R.id.txtVw);
        txtVw.setText(result);
    }
}

更新1

在聊天中,Jigs建议尝试'runOnUiThread',但onPostExecute已经在UI线程上运行,所以不幸的是它有点无关紧要。我想我正在尝试做的不是阻止UI,而onPostExecute的行为本质上是一个UI阻塞,这使得它变得不可能。如果有人有不同的想法,我会留下问题!

0 个答案:

没有答案