Instantiating a View on non-UI thread

纵饮孤独 提交于 2019-12-10 10:17:14

问题


I know that the UI elements (View hierarchy) may only be manipulated from the UI thread. For a background operation, the AsyncTask can be used, which offers event handlers to reach the UI thread.

To be brief, is it allowed to instantiate a View (tied to getApplicationContext()) in a non-UI thread? This custom View descendant -- once instantiated -- is added to the view hierarchy from the UI thread. So only the constructor call is done inside an Asynctask.doInBackground(); it's attaching (addView(...)) to the Activity's root layout hierarchy is still done in the UI thread.

In details:

public MyView extends View {
     public MyView(Context context) { 
            ...
     }
...
}
  1. I made a custom View, with overriden onDraw(...) etc.

  2. When the user clicks a certain MenuItem in my main Activity, another Activity (MyOtherActivity) is created and displayed which screen is exactly MyView

  3. Since the screen of MyOtherActivity must be displayed instantly, I pre-instantiate MyView in an AsyncTask while the user is somewhere else in the main Activity (i.e. he hasn't clicked that MenuItem yet). The MyView reference is stored in a static data member.

  4. When MyOtherActivity.onCreate() is called, its constructor code takes MyView from the static, and adds it to its layout root hierarchy via addView(...).

  5. (I'm aware that the static variable may introduce memory leaks, so I set it to null once it's not needed.)

Isn't it a problem (and might it introduce unexpected issues) that MyView is instantiated in a different thread (and takes the return value of getApplicationContext() in its constructor)?


回答1:


The definitive answer appears in the documentation for View, under the heading "Event Handling and Threading":

Note: The entire view tree is single threaded. You must always be on the UI thread when calling any method on any view. If you are doing work on other threads and want to update the state of a view from that thread, you should use a Handler.

So it's not just things that obviously affect the appearance of the UI, like addView(), but "any method on any View".

The discussion on android-developers that @CommonsWare linked to has more than one high-level engineer from the Android framework team confirming that this is to be taken seriously.




回答2:


This is an example, in how to add a view to a FrameLayout using AsyncTask

public void addFLview(View view) {
    MyAsyncTask as = new MyAsyncTask();
    as.execute(view);
}

AsyncTask class

private class MyAsyncTask extends AsyncTask<View, Void, View> {
    @Override
    protected View doInBackground(View... params) {
        return params[0];
    }
    @Override
    protected void onPostExecute(View view) {
        super.onPostExecute(view);
        myFrameLayout.addView(view);
    }
}


来源:https://stackoverflow.com/questions/11215302/instantiating-a-view-on-non-ui-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!