首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Android UI线程消息队列调度顺序

Android UI线程消息队列调度顺序
EN

Stack Overflow用户
提问于 2013-11-14 04:58:40
回答 2查看 8.9K关注 0票数 62

当使用Android中的保留片段在配置更改期间保存AsyncTask时,我想这是最好的方法,但我对UI线程的消息队列调用顺序产生了一些疑问。

例如:想象一下这个场景:

发生

  1. 配置更改时,用户旋转设备。is running.
  2. Fragment AsyncTask is finishes
  3. AsyncTask doInBackground() onPostExecute()is AsyncTask onDetach() is running.
  4. Fragment

doInBackground()onPostExecute()is called

  1. AsyncTask onDetach()is called
  2. Fragment onAttach() is

那么UI线程消息队列可以是这样的吗:

队列顶部-> onDetach() | onPostExecute() | onAttach()

我知道不能,据我所知,对onPostExecute()的调用将等待配置更改完成,但这是如何工作的呢?来自活动、片段生命周期的调用是否连续执行?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-26 03:06:52

在配置更改期间,不可能在Fragment#onDetach()Fragment#onAttach()之间调用onPostExecute()。这种说法背后的理由有三个:

  1. 配置更改在主线程的消息队列中的单个消息中进行处理。
  2. 只要doInBackground()方法返回,AsyncTask就会通过将一条消息发布到主线程的消息队列来调度要在主线程上调用的onPostExecute()方法。
  3. 配置更改的消息将包含将调用<代码>D12和<代码>D13生命周期方法(如<代码>D14和<代码>D15)的代码。AsyncTask的消息将包含调用onPostExecute()方法的代码。由于主线程按顺序处理其消息队列中的消息,因此不可能同时执行这两个消息,因此永远不能在调用onPostExecute()onDetach()之间调用onDetach()

请阅读我在this thread中对Doug Stevenson的回复,了解更详细的解释(包括证明该主张的源代码的链接)。

票数 119
EN

Stack Overflow用户

发布于 2019-11-22 12:51:51

我编写了一个简单的测试来查看保留的Fragment中的AsyncTask的生命周期。它可以确认@Alex Lockwood的答案是真的。因此,可以肯定地说,保留Fragment中的AsyncTask是最佳实践。谷歌应该将这种方法写入他们的官方文件中。

public class RecordDataFragment extends Fragment {
    public static boolean detach = false;

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

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Timber.d("retain, onAttach");
        detach = false;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Timber.d("retain, onDetach");
        detach = true;
    }

    public static class TestTask extends AsyncTask<String, Void, Void> {

        protected Void doInBackground(String... username) {

            Timber.d("retain, looping.");

            while(!detach){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            Timber.d("retain, exit looping.");

            return null;
        }

        protected void onPostExecute(Void nothing) {
            Timber.d("retain, onPostExecute");
        }
    }
}

public class RecordFragment extends Fragment {

    static boolean called = false;

    @Override
    public void onResume() {
        super.onResume();
        Timber.d("retain, onResume");

        if(!called) {
            new RecordDataFragment.TestTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
            called = true;
        }

    }
}

2019-11-22 12:28:55.503 D/RecordDataFragment: retain, onAttach
2019-11-22 12:32:00.263 D/RecordFragment: retain, onViewStateRestored
2019-11-22 12:32:03.538 D/RecordFragment: retain, onResume
2019-11-22 12:32:03.544 D/RecordDataFragment$TestTask: retain, looping.
2019-11-22 12:32:07.273 D/RecordDataFragment: retain, onDetach
2019-11-22 12:32:07.297 D/RecordDataFragment$TestTask: retain, exit looping.
2019-11-22 12:32:07.403 D/RecordFragment: retain, onDestroy
2019-11-22 12:32:07.566 D/RecordDataFragment: retain, onAttach
2019-11-22 12:32:08.621 D/RecordFragment: retain, onViewStateRestored
2019-11-22 12:32:08.870 D/RecordFragment: retain, onResume
2019-11-22 12:32:09.663 D/RecordDataFragment$TestTask: retain, onPostExecute
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19964180

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档