私は非常に簡単な質問をします:
バックグラウンドスレッド(例:doInBackground
)でビューを(レイアウトに追加しないで)ビューをインフレートできるかどうかAsyncTask
)の?
私はバックグラウンドスレッドでViews
を膨らませないべきですと言われましたが、具体的な理由は何ですか?なぜ私のアプローチはほとんどのデバイスでは機能しませんがGalaxy S?
LayoutInflater
は、どのスレッドで実行されているかについては何も想定していません。そして、そのドキュメントではこれについて何も言及されていません。また、そのコードはスレッドにとらわれないように継ぎ合わせています。
一方、LayoutInflater
によって作成されたビューは、コンストラクターでHandler
sをインスタンス化する場合があります。まあ、おそらくそうすべきではありませんが、コンストラクターでHandler
sを作成/使用しないという要件はありません。
私の推測では、Samsung Galaxy SのEditText
にいくつかの変更が加えられ、何らかの形でHandler
の作成がトリガーされたと思われます(GestureDetector
の他の質問インスタンスからのクラッシュログによると、新しいHandler
)を作成します。デフォルトの実装はこれを行いませんが。
全体として、コンストラクターでView
sおよびHandler
sを使用しないというLooper
sの明示的な要件がないため、非UIからのビューの拡張を想定できないと思いますスレッドは安全です。
実際に HandlerThread
を作成し、その内部でView
sを膨らませることができます。ただし、Samsung Galaxy Sの例のように、ビューはこのスレッドがView
の存続期間中は有効であり、Looper
を使用してすべてのメッセージを処理すると想定しているため、これは非常に危険だと思います。後でクラッシュする可能性があります。
最新のサポートライブラリを使用すると、 Android.support.v4.view.AsyncLayoutInflater
非同期にビューを拡張します。ただし、特定の要件が満たされていない場合は、UIスレッドの拡張にフォールバックする可能性があるので注意してください。
レイアウトを非同期的に膨張させるには、generateLayoutParams(AttributeSet)がスレッドセーフである親が必要であり、インフレーションの一部として構築されるすべてのビューは、ハンドラーを作成したり、myLooper()を呼び出したりしてはなりません。何らかの理由でインフレートしようとしているレイアウトを非同期で構築できない場合、AsyncLayoutInflaterは自動的にUIスレッドのインフレーションにフォールバックします。
バックグラウンドスレッド(例:AsyncTaskのdoInBackground内)でビューを膨張させる(レイアウトに追加しない)ことは可能ですか、それとも不可能ですか?
はい、可能です。おすすめですか?いいえ。ドキュメントに記載されているとおり:
したがって、Androidのシングルスレッドモデルには2つのルールがあります。
- UIスレッドをブロックしない
- Android UIツールキットにはUIスレッドの外部からアクセスしないでください
経由: プロセスとスレッド
更新[02/06/19]:
どうやら、サポートライブラリにはこれを行うツールがあります: AsyncLayoutInflater ( Jetpack version )。バージョン24、2016年頃に導入されました(私の回答から2年後)
ただし、他の回答で述べたように、このツールは非常に簡単に裏目に出る可能性があるため、注意が必要です。