42

非常に簡単な質問があります。

バックグラウンド スレッド (例: の ) でビューをインフレートする (レイアウトに追加しない)ことは可能ですか? doInBackgroundAsyncTask

Galaxy S: Android: android.view.InflateException: Binary XML file line #13: Error SAMSUNG Galaxy S のクラス <unknown> の膨張

バックグラウンド スレッドでインフレするべきではないと言われましたViewsが、具体的な理由は何ですか? また、私のアプローチがほとんどのデバイスで機能するのに、Galaxy S では機能しないのはなぜですか?

4

3 に答える 3

45

LayoutInflater、どのスレッドで実行されるかについては何も想定していません。そして、そのドキュメントにはこれについて何も言及されていません。また、そのコードはスレッドに依存しないように継ぎ目があります。

一方、によって作成されたビューは、コンストラクターでsをLayoutInflaterインスタンス化する場合があります。Handlerまあ、彼らはおそらくそれをすべきではありませんが、コンストラクターでsを作成/使用しないという要件はありませんHandler

私の推測では、Samsung Galaxy Sにはいくつかの変更が加えられておりEditText、何らかの形での作成がトリガーHandlerされます(他の質問インスタンスからのクラッシュログによると、GestureDetectorインスタンス化されて新しいものが作成されましたHandler)。デフォルトの実装はこれを行いませんが。


全体として、コンストラクターでsとsをView使用しないという明示的な要件がないため、非UIスレッドからのビューの拡張が安全であるとは想定できません。HandlerLooper

実際に作成して、その内部でsをHandlerThread膨らませてみることができます。Viewただし、Samsung Galaxy Sの例では、このスレッドは存続期間中View存続し、そのスレッドを使用してすべてのメッセージを処理すると想定しているため、これは非常に危険Looperです。後でクラッシュする可能性があります。

于 2011-07-14T10:48:03.940 に答える
5

バックグラウンド スレッド (例: AsyncTask の doInBackground) でビューをインフレートする (レイアウトに追加しない) ことは可能ですか?

可能です、はい。おすすめされた?いいえ。ドキュメントに記載されているとおり:

したがって、Android のシングル スレッド モデルには 2 つのルールがあります。

  1. UI スレッドをブロックしない
  2. UI スレッドの外部から Android UI ツールキットにアクセスしないでください。

経由:プロセスとスレッド

更新 [02/06/19]:

どうやら、サポート ライブラリにはこれを行うためのツールがあります: AsyncLayoutInflater ( Jetpack バージョン)。2016年頃のバージョン24で導入されました(私の回答から2年後)

ただし、他の回答で述べたように、このツールは非常に簡単に裏目に出る可能性があるため、注意してください。

于 2014-02-03T12:08:43.597 に答える