Android 在背景线程中膨胀视图
我有一个非常简单的问题: 是否可以在后台线程(例如:在Android 在背景线程中膨胀视图,android,multithreading,thread-safety,inflate,Android,Multithreading,Thread Safety,Inflate,我有一个非常简单的问题: 是否可以在后台线程(例如:在AsyncTask的doInBackground中)中对视图进行充气(而不是将其添加到布局中) 我知道这是可能的,因为我已经以这种方式实现了应用程序中的大多数活动,并且从来没有遇到过问题,直到我在Galaxy S上遇到这个问题: 有人告诉我,我不应该在后台线程中膨胀视图,但具体原因是什么?为什么我的aproach在大多数设备中都能工作,而在Galaxy S中却不能工作?LayoutInflater没有对它在哪个线程上运行做出任何假设。在它的文
AsyncTask
的doInBackground
中)中对视图进行充气(而不是将其添加到布局中)
我知道这是可能的,因为我已经以这种方式实现了应用程序中的大多数活动,并且从来没有遇到过问题,直到我在Galaxy S上遇到这个问题:
有人告诉我,我不应该在后台线程中膨胀
视图,但具体原因是什么?为什么我的aproach在大多数设备中都能工作,而在Galaxy S中却不能工作?LayoutInflater
没有对它在哪个线程上运行做出任何假设。在它的文档中没有提到这一点。而且它的代码接缝是线程不可知的
另一方面,由LayoutInflater
创建的视图可能会在其构造函数中实例化Handler
s。嗯,他们可能不应该这样做,但是没有要求他们不在构造函数中创建/使用处理程序
我的猜测是三星Galaxy S在其EditText
中进行了一些修改,以某种方式触发了处理程序的创建(根据您的另一个问题中的崩溃日志,GestureDetector
的实例被实例化,从而创建了新的处理程序
)。而默认实现并不能做到这一点
总的来说,我要说的是,因为没有明确要求视图
s在其构造函数中不使用处理程序
s和循环器
s,所以不能假设从非UI线程中膨胀视图是安全的
实际上,您可以创建并尝试在其内部膨胀视图
s。但我认为这是非常危险的,因为在三星Galaxy S的示例中,视图假设此线程在view
生命周期内处于活动状态,并将使用其活套处理所有消息。这可能会导致以后的崩溃
是否可以在后台线程(例如,在异步任务的doInBackground中)中膨胀视图(而不是将其添加到布局)
有可能,是的。推荐?编号。如文件中所述:
因此,Android的单线程模型只有两条规则:
不要阻塞UI线程
不要从UI线程外部访问Android UI工具包
通过:
更新[02/06/19]:
显然,支持库有一个工具可以做到这一点:
(). 它在2016年左右的第24版中引入(在我回答后2年)
但是,正如其他答案中提到的,使用此工具时要小心,因为它很容易适得其反。使用最新的支持库,您可以异步扩展视图。但要小心,如果不满足特定要求,它可能会退回到UI线程上膨胀:
对于要异步膨胀的布局,它需要有一个其父级,其generateLayoutParams(AttributeSet)是线程安全的,并且作为膨胀的一部分构造的所有视图不得创建任何处理程序或以其他方式调用myLooper()。如果由于任何原因无法异步构建尝试充气的布局,AsyncLayoutFlater将自动退回到UI线程上充气
我在运行最新库存固件的Galaxy Nexus上重现了同样的问题(截至本文)。在后台膨胀视图肯定不再是一个选项。HandlerThread将消息转发到MainLoop应该可以解决此问题