在后台线程中膨胀视图

发布于 2024-11-20 00:40:53 字数 494 浏览 4 评论 0原文

我有一个非常简单的问题:

是否可以在后台线程中膨胀视图(不将其添加到布局中)(例如:在AsyncTask)?

我知道这是可能的,因为我已经以这种方式在应用程序中实现了大多数活动并且从未遇到过问题,直到我在 Galaxy S 上遇到此问题: Android: android.view.InflateException: 二进制 XML 文件行 #13: 错误膨胀类<未知>在 SAMSUNG Galaxy S 中,

我被告知我不应该在后台线程中膨胀视图,但是具体原因是什么以及为什么我的方法在大多数设备,但 Galaxy S 中没有?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

も星光 2024-11-27 00:40:53

LayoutInflater 不会对其运行的线程做出任何假设。它的文档中没有提到这一点。而且它的代码似乎与线程无关。

另一方面,由 LayoutInflater 创建的视图可能会在其构造函数中实例化 Handler。好吧,他们可能不应该这样做,但是没有要求他们不在构造函数中创建/使用 Handler 。

我的猜测是,三星 Galaxy S 在其 EditText 中进行了一些修改,以某种方式触发了 Handler 的创建(根据 GestureDetector 的其他问题实例的崩溃日志) code> 被实例化,进而创建了新的 Handler)。虽然默认实现不会这样做。


总的来说,我想说,因为没有明确要求 View 在其构造函数中不使用 HandlerLooper,所以您可以不要假设从非 UI 线程膨胀视图是安全的。

您实际上可以创建 HandlerThread 并尝试膨胀View位于其中。但我想说这是非常危险的,因为在三星 Galaxy S 示例中,视图假设该线程在 View 生命周期内处于活动状态,并将使用其 Looper 处理所有消息。这可能会导致稍后崩溃。

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.

甜`诱少女 2024-11-27 00:40:53

使用最新的支持库,您可以使用 android.support.v4 .view.AsyncLayoutInflater 异步膨胀视图。但请注意,如果不满足特定要求,它可能会回退到 UI 线程上进行膨胀:

对于要异步膨胀的布局,它需要有一个父级,其generateLayoutParams(AttributeSet)是线程安全的,并且作为膨胀的一部分构造的所有视图不得创建任何处理程序或以其他方式调用myLooper()。如果尝试膨胀的布局由于某种原因无法异步构造,AsyncLayoutInflater 将自动回退到 UI 线程上膨胀。

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.

青春有你 2024-11-27 00:40:53

是否可以在后台线程中(例如:在 AsyncTask 的 doInBackground 中)膨胀视图(不将其添加到布局中)?

有可能,是的。受到推崇的?否。正如文档中所述:

因此,Android 的单线程模型只有两条规则:

  1. 不要阻塞 UI 线程
  2. 不要从 UI 线程外部访问 Android UI 工具包

通过以下方式从 UI 线程外部访问 Android UI 工具包: 进程和线程

更新 [02/06/19]:

显然,支持库有一个工具可以做到这一点:
AsyncLayoutInflater (Jetpack 版本)。它是在 2016 年左右的版本 24 中引入的(我的回答两年后)

但是,正如其他答案中提到的,要小心这个工具,因为它很容易适得其反。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文