Inflate a view in a background thread

给你一囗甜甜゛ 提交于 2019-12-17 10:46:08

问题


I have a very simple question:

Is or is it not possible to inflate a view (not add it to layout) in a background thread (ex: in the doInBackground of an AsyncTask)?

I know that it is possible, because I have implemented most Activities in my application this way and never had a problem, until I had this problem on a Galaxy S: Android: android.view.InflateException: Binary XML file line #13: Error inflating class <unknown> in SAMSUNG Galaxy S

I've been told that I should not inflate Views in background threads, but what are the specific reasons and why does my aproach work in most devices but not in Galaxy S?


回答1:


The LayoutInflater does not make any assumptions about what thread it runs on. And nothing is mentioned about this in its documentation. Also its code seams to be thread-agnostic.

On the other hand, Views that are created by LayoutInflater might instantiate Handlers in their constructors. Well, they probably shouldn't do that, but there is no requirement for them to not create/use Handlers in their constructors.

My guess is that Samsung Galaxy S had some modifications in its EditText that somehow triggers creation of Handler (according to crash log from your other question instance of GestureDetector was instantiated which in turn created new Handler). While default implementation doesn't do this.


Overall, I'd say that because there is no explicit requirement for Views to not use Handlers and Loopers in their constructors you can't assume inflating Views from non-UI thread is safe.

You can actually create HandlerThread and try inflating Views inside it. But I'd say this is very risky, as in Samsung Galaxy S example the view assumes that this thread will be alive during View lifetime and will process all messages using its Looper. Which might result in crash later on.




回答2:


With latest support lib you can use android.support.v4.view.AsyncLayoutInflater to inflate views asynchronously. Be careful though that it can fallback to inflating on UI thread if specific requirements are not met:

For a layout to be inflated asynchronously it needs to have a parent whose generateLayoutParams(AttributeSet) is thread-safe and all the Views being constructed as part of inflation must not create any Handlers or otherwise call myLooper(). If the layout that is trying to be inflated cannot be constructed asynchronously for whatever reason, AsyncLayoutInflater will automatically fall back to inflating on the UI thread.




回答3:


Is or is it not possible to inflate a view (not add it to layout) in a background thread (ex: in the doInBackground of an AsyncTask)?

Possible, yes. Recommended? No. As mentioned in the documentation:

Thus, there are simply two rules to Android's single thread model:

  1. Do not block the UI thread
  2. Do not access the Android UI toolkit from outside the UI thread

via: Processes and Threads

Update [02/06/19]:

Apparently, the support library has a tool to do this: AsyncLayoutInflater (Jetpack version). It was introduced in version 24, around 2016 (2 years after my answer)

But, as mentioned on other answers, be careful with this tool as it can very easily backfire.



来源:https://stackoverflow.com/questions/6691311/inflate-a-view-in-a-background-thread

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