我有一个非常简单的问题:
在背景线程中是否膨胀一个视图(不是将其添加到布局)(例如:doInBackground
的{{1}})?
我知道这是可能的,因为我已经以这种方式在我的应用程序中实现了大多数活动,并且从未出现问题,直到我在Galaxy S上遇到此问题:Android: android.view.InflateException: Binary XML file line #13: Error inflating class <unknown> in SAMSUNG Galaxy S
我被告知我应该不会在后台线程中膨胀AsyncTask
,但具体原因是什么?为什么我的aproach在大多数设备上工作但在Galaxy S中没有?
答案 0 :(得分:39)
LayoutInflater
不会对其运行的线程做出任何假设。在其文档中没有提到这一点。它的代码也与线程无关。
另一方面,LayoutInflater
创建的视图可能会在其构造函数中实例化Handler
。好吧,他们可能不应该这样做,但是没有要求他们不在他们的构造函数中创建/使用Handler
。
我的猜测是,三星Galaxy S在其EditText
中进行了一些修改,以某种方式触发了Handler
的创建(根据您GestureDetector
的其他问题实例的崩溃日志实例化了转而创建新的Handler
)。虽然默认实现不会这样做。
总的来说,我之所以这么说,是因为没有明确要求View
s在其构造函数中不使用Handler
和Looper
,因此您无法假设非UI线程是安全的。
您实际上可以创建HandlerThread
并尝试在其中充气View
。但我认为这是非常危险的,因为在三星Galaxy S示例中,该视图假定此线程在View
生命周期内将处于活动状态,并将使用其Looper
处理所有消息。这可能会导致以后崩溃。
答案 1 :(得分:13)
使用最新的支持库,您可以使用android.support.v4.view.AsyncLayoutInflater
异步扩充视图。但要小心,如果不满足特定要求,它可以回退到UI线程上膨胀:
对于要异步膨胀的布局,它需要有一个父类,其generateLayoutParams(AttributeSet)是线程安全的,并且构造为通胀的一部分的所有视图都不能创建任何处理程序或以其他方式调用myLooper()。如果由于某种原因无法异步构造试图膨胀的布局,AsyncLayoutInflater将自动回退到UI线程上的膨胀。
答案 2 :(得分:2)
是否或者不可能在后台线程中扩展视图(不将其添加到布局)(例如:在AsyncTask的doInBackground中)?
可能,是的。推荐的?不。如文档中所述:
因此,Android的单线程模型只有两个规则:
- 不要阻止UI线程
- 不要从UI线程外部访问Android UI工具包
醇>