pan*_*dre 35 multithreading android thread-safety inflate
我有一个非常简单的问题:
是否还是无法充气视图(不将它添加到布局)在后台线程(例如:在doInBackground
的AsyncTask
)?
我知道这是可能的,因为我已经在我的应用程序中以这种方式实现了大多数活动并且从未出现过问题,直到我在Galaxy S上遇到此问题: Android:android.view.InflateException:二进制XML文件行#13:错误在SAMSUNG Galaxy S中膨胀类<未知>
我被告知我不应该Views
在后台线程中膨胀,但具体原因是什么,为什么我的aproach在大多数设备中工作但在Galaxy S中没有?
ina*_*ruk 39
该LayoutInflater
不会使什么线程运行在任何假设.在其文档中没有提到这一点.它的代码接缝也与线程无关.
另一方面,由LayoutInflater
might 创建的视图可以Handler
在其构造函数中实例化s.好吧,他们可能不应该那样做,但是没有要求他们不在Handler
他们的构造函数中创建/使用s.
我的猜测是三星Galaxy S在其中有一些修改EditText
,以某种方式触发创建Handler
(根据你的其他问题实例的崩溃日志实例GestureDetector
化,反过来创建新的Handler
).虽然默认实现不会这样做.
总的来说,我会说,因为没有明确要求View
s不在其构造函数中使用Handler
s和Looper
s,所以不能假设来自非UI线程的膨胀视图是安全的.
你实际上可以创建HandlerThread
并尝试View
在其中充气.但我认为这是非常危险的,因为在三星Galaxy S示例中,该视图假定此线程在View
生命周期内将处于活动状态并将使用其处理所有消息Looper
.这可能会导致以后崩溃.
M-W*_*eEh 13
使用最新的支持库,您可以使用android.support.v4.view.AsyncLayoutInflater
异步扩展视图.但要小心,如果不满足特定要求,它可以回退到UI线程上的膨胀:
对于要异步膨胀的布局,它需要有一个父类,其generateLayoutParams(AttributeSet)是线程安全的,并且构造为通胀的一部分的所有视图都不能创建任何处理程序或以其他方式调用myLooper().如果由于某种原因无法异步构造试图膨胀的布局,AsyncLayoutInflater将自动回退到UI线程上的膨胀.
是否可以在后台线程(例如:在 AsyncTask 的 doInBackground 中)扩充视图(而不是将其添加到布局)?
可能,是的。受到推崇的?否。如文档中所述:
因此,Android 的单线程模型只有两条规则:
- 不要阻塞 UI 线程
- 不要从 UI 线程之外访问 Android UI 工具包
通过:进程和线程
更新 [02/06/19]:
显然,支持库有一个工具可以做到这一点: AsyncLayoutInflater(Jetpack 版本)。它是在 24 版中引入的,大约在 2016 年(我的回答后 2 年)
但是,正如其他答案中提到的,请小心使用此工具,因为它很容易适得其反。