代码之家  ›  专栏  ›  技术社区  ›  Javi

Android中广播接收器的奇怪问题

  •  0
  • Javi  · 技术社区  · 15 年前

    我只有这段代码,非常简单。我有一个列表,在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);
        }
    }
    

    谢谢

    1 回复  |  直到 15 年前
        1
  •  4
  •   Binh Tran    15 年前

    首先,我认为我们应该了解一些事实:

    • 活动将在调用onresume()方法后开始绘制其内容,但不是在“之后”开始绘制。
    • 调用listview.setlistadapter(…)之后,listview只存储适配器对象,此时没有子视图。
    • 在ListView在屏幕上绘制该子视图(在调用adapter.getView()之后)之后,子视图将可用,并且每次ListView添加一个子视图时,子视图列表将逐个增加,直到ListView在屏幕上绘制所有子视图。

    对于您的代码,您不能在活动第一次启动时获得子视图列表的原因是“ListView没有在屏幕上绘制任何内容”。因为接收者的onReceive()方法是在ListView绘制之前触发的。

    您可以通过重写适配器和显示日志来检查这一点,以查看调用这些方法的顺序。 以下是我的结果:

    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
    

    希望我的回答能帮助你!