1

标题说明了一切。好吧,主要是。这只发生在 1 台设备上。其他设备没问题。

在我调用下面的代码中,onPostExecute得到这个异常之前我没有,添加了可运行对象,因为我得到了 CalledFromWrongThreadException 异常。AsyncTaskrunOnUiThread


编辑

这是我发现的。在某些情况下,一个应用程序可以有多个“循环器”,因此可以有多个“UI 线程”。

由于一个应用程序可以有多个“UI 线程”并且一个 AsyncTask 总是“在 UI 线程上运行”[ref],有人决定 [糟糕] 而不是 AsyncTask 总是在其创建线程上运行(在 99.999999% 的情况下将是正确的“UI 线程”)他们决定使用 hocus pocus(或制作不佳的快捷方式,您决定)在“主循环器”上执行..

Android:在 onPostExecute() 中得到 CalledFromWrongThreadException - 怎么可能?

所以现在看来​​我需要找到一种方法来确保异步任务线程始终是应用程序所在的循环线程:(


getParentActivity().runOnUiThread(new Runnable()
{
        @Override
        public void run()
        {
            setAdapterData(result);
        }
});

当那不起作用时,我也尝试了这个,并一起尝试了它们。

lvUpdatesList.post(new Runnable()
{
    @Override
    public void run()
    {
        lvUpdatesList.setAdapter(updateListAdapter);
    }
});

我对它为什么会这样表现感到非常困惑。

07-03 13:19:51.908: E/AndroidRuntime(4479): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.view.ViewRoot.checkThread(ViewRoot.java:2932)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.view.ViewRoot.invalidateChild(ViewRoot.java:642)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:668)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.view.ViewGroup.invalidateChild(ViewGroup.java:2511)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.view.View.invalidate(View.java:5279)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.widget.AbsListView.resetList(AbsListView.java:1120)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.widget.ListView.resetList(ListView.java:511)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.widget.ListView.setAdapter(ListView.java:440)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at com.********.********.FragmentUpdates.setAdapterData(FragmentUpdates.java:213)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at com.********.********.FragmentUpdates$AsyncGetUpdates.onPostExecute(FragmentUpdates.java:185)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at com.********.********.FragmentUpdates$AsyncGetUpdates.onPostExecute(FragmentUpdates.java:1)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.os.AsyncTask.finish(AsyncTask.java:417)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.os.AsyncTask.access$300(AsyncTask.java:127)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.os.Looper.loop(Looper.java:130)
07-03 13:19:51.908: E/AndroidRuntime(4479):     at android.os.HandlerThread.run(HandlerThread.java:60)

完整的异步任务

class AsyncGetUpdates extends AsyncTask<Void, Void, List<UpdateDTO>>
    {

        String userId;

        @Override
        protected void onPreExecute()
        {
            showDialog();
            userId = getParentActivity().getCurrentUser().getUser_id();
            super.onPreExecute();
        }

        @Override
        protected List<UpdateDTO> doInBackground(Void... params)
        {
            boolean followingOnly = false;
            if (myState == MyState.Following)
                followingOnly = true;

            return APIHelper.getUpdates(userId, followingOnly, count);
        }

        @Override
        protected void onPostExecute(final List<UpdateDTO> result)
        {
            killDialog();
            isCurrentlyUpdating = false;
            getParentActivity().runOnUiThread(new Runnable()
            {
                @Override
                public void run()
                {
                    setAdapterData(result);
                }
            });
            super.onPostExecute(result);
        }

    }
4

1 回答 1

2

对于未来如果人们有这个问题,你不会在任何发布的 JellyBean 设备中,这就是你解决它的方法。

你在你的应用程序中做的第一件事就是这个。

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_splash);

    this.runOnUiThread(new Runnable()
    {
        @Override
        public void run()
        {
            new AsyncInitLooperTask().execute();
        }
    });
     }

public class AsyncInitLooperTask extends AsyncTask<Void, Void, Void>
{
    @Override
    protected Void doInBackground(Void... params)
    {
        return null;
    }
}

这样做会将InternalHandler处理 AsyncTasks 的应用程序附加到应用程序正在使用的正确 Looper/UIThread 上。

于 2013-07-03T20:11:27.053 回答