4

UI 要素 (ビュー階層) は UI スレッドからのみ操作できることを知っています。バックグラウンド操作の場合、UI スレッドに到達するイベント ハンドラーを提供する AsyncTask を使用できます。

簡単に言うと、getApplicationContext()UI 以外のスレッドでビュー (に関連付けられている) をインスタンス化することは許可されていますか? このカスタム ビューの子孫は、インスタンス化されると、UI スレッドからビュー階層に追加されます。したがって、コンストラクターの呼び出しのみがAsynctask.doInBackground();内で行われます。addView(...)アクティビティのルート レイアウト階層へのアタッチ ( ) は、引き続き UI スレッドで行われます。

詳細に:

public MyView extends View {
     public MyView(Context context) { 
            ...
     }
...
}
  1. onDraw(...)オーバーライドなどを使用して、カスタム ビューを作成しました。

  2. ユーザーがメイン アクティビティの特定の MenuItem をクリックすると、別のアクティビティ (MyOtherActivity) が作成されて表示されます。この画面はまさに MyView です。

  3. MyOtherActivity の画面はすぐに表示する必要があるため、ユーザーがメイン アクティビティの別の場所にいる間 (つまり、その MenuItem をまだクリックしていないとき)、AsyncTask で MyView を事前にインスタンス化します。MyView 参照は、静的データ メンバーに格納されます。

  4. MyOtherActivity.onCreate()呼び出されると、そのコンストラクター コードは静的から MyView を取得し、それを を介してレイアウト ルート階層に追加しますaddView(...)

  5. (静的変数がメモリリークを引き起こす可能性があることは承知しているので、null不要になったら一度に設定します。)

MyView が別のスレッドでインスタンス化される (およびgetApplicationContext()そのコンストラクターで戻り値を取る) ことは問題ではありませんか (予期しない問題が発生する可能性があります)。

4

2 に答える 2

5

決定的な答えは、Viewのドキュメントの「イベント処理とスレッド化」という見出しの下に表示されます。

注:ビューツリー全体がシングルスレッドです。ビューでメソッドを呼び出すときは、常にUIスレッドを使用している必要があります。他のスレッドで作業を行っていて、そのスレッドのビューの状態を更新する場合は、ハンドラーを使用する必要があります。

つまり、UIの外観に明らかに影響を与えるのは、のようなものだけではaddView()なく、「任意のビューの任意のメソッド」です

@CommonsWareがリンクしているandroid-developersに関するディスカッションには、Androidフレームワークチームの複数の高レベルのエンジニアがいて、これが真剣に受け止められることを確認しています。

于 2012-06-27T00:49:29.623 に答える
0

これは、AsyncTask を使用して FrameLayout にビューを追加する方法の例です。

public void addFLview(View view) {
    MyAsyncTask as = new MyAsyncTask();
    as.execute(view);
}

AsyncTask クラス

private class MyAsyncTask extends AsyncTask<View, Void, View> {
    @Override
    protected View doInBackground(View... params) {
        return params[0];
    }
    @Override
    protected void onPostExecute(View view) {
        super.onPostExecute(view);
        myFrameLayout.addView(view);
    }
}
于 2014-11-06T19:44:05.610 に答える