0

私は非常に単純なこのコードを持っています。リストがあり、onCreate メソッドでこのリストにいくつかのオブジェクトを追加して、それらを画面に表示しました。インターネット接続がない場合、リストのいくつかの要素を有効/無効にする必要があるブロードキャストレシーバーがあります。

アプリケーションが既にこのアクティビティの画面にあるときに接続が失われた場合、ブロードキャスト レシーバーは正常に動作します。問題は、このアクティビティに入る前に接続がない場合です。この場合、onresume() で oncreate() メソッドを呼び出した後、レシーバーは登録されますが、レシーバー内で getListView() を呼び出すと、子がありません (ただし、oncreate メソッドでアダプターに追加し、私はロードしておらず、スレッドをまったく使用していません)。

なぜこれが起こっているのか誰にも教えてもらえますか?

public class MyActivity extends ListActivity {
    private List<MyClass> myObjects;

    private final BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            //check if internet connection is available
            boolean networkAvailable = ... ;
            if (!networkAvailable) {
                //No Internet connection: disabled non-cached objects
                List<MyClass> cachedObjects = getCachedObjects();
                for(int i = 0; i<myObjects.size(); i++){
                    MyClass myObject = myObjects.get(i);
                    if (!cachedSurveys.contains(myObject)) {
                        ListView listView = getListView();
                        //The problem is here: listView is empty when there was no connection
                        //before creating the activity so the broadcast receiver was called in a sticky way                     
                        View child = listView.getChildAt(i);
                        child.setEnabled(false);

                    }
                }
            } else {
                // Internet connection: enable all myObjects
                 int size = getListView().getChildCount();
                 for (int i = 0; i < size; i++) {
                    View child = getListView().getChildAt(i);
                    child.setEnabled(true);
                }
            }
        }
     }; 

     @Override
     public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        myObjects = getMyObjects();

        setListAdapter(new ArrayAdapter<MyClass>(this, android.R.layout.simple_list_item_1, myObjects));
        getListView().setTextFilterEnabled(true);   
}

    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter intentFilter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
        registerReceiver(receiver, intentFilter);
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(receiver);
    }
}

ありがとう

4

1 に答える 1

4

まず、いくつかの事実を確認する必要があると思います。

  • アクティビティは、onResume() メソッドが呼び出された後にコンテンツの描画を開始しますが、「直後」ではありません。
  • ListView.setListAdapter(...) を呼び出した後、ListView はアダプター オブジェクトのみを格納します。その時点では、子ビューはありません。
  • 子ビューは、ListView がその子を画面に描画した後 (Adapter.getView() が呼び出された後) に使用可能になり、子ビュー リストは、ListView が子ビューを 1 つ追加するたびに、ListView がすべての子ビューを画面に描画するまで 1 つずつ増加します。 .

また、あなたのコードでは、最初のアクティビティ開始時に子ビュー リストを取得できない理由は、「ListView が画面に何も描画していない」ためです。ListView が描画される前に、レシーバーの onReceive() メソッドがトリガーされるためです。

アダプターをオーバーライドしてログを表示し、これらのメソッドが呼び出される順序を確認することで、自分で確認できます。ここに私の結果があります:

07-30 23:06:03.231: DEBUG/MyActivity(386): onResume 1280505963237   
07-30 23:06:03.281: DEBUG/MyActivity(386): onReceive 1280505963281
07-30 23:06:03.361: DEBUG/MyActivity(386): getView 0 1280505963371
07-30 23:06:03.381: DEBUG/MyActivity(386): getView 1 1280505963386

私の答えがあなたに役立つことを願っています!

于 2010-07-30T16:20:31.617 に答える