简体   繁体   English

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

[英]Strange problem with broadcast receiver in Android

I have just this piece of code which is quite simple. 我只有一段很简单的代码。 I have a list and in the onCreate method I added some objects to this list to show them on the screen. 我有一个列表,在onCreate方法中,我向该列表中添加了一些对象以在屏幕上显示它们。 I have a broadcast receiver which has to enable/disable some elements of the list when there aren't internet connection. 我有一个广播接收器,当没有互联网连接时,它必须启用/禁用列表中的某些元素。

The broadcast receiver works good if the connection is lost when the application is already in the screen of this activity. 如果应用程序已经在此活动的屏幕中,则连接断开时,广播接收器会很好地工作。 The problem is when there is no connection before entering this activity. 问题是进入此活动之前没有连接时。 In this case after calling oncreate() method in the onresume() the receiver is registered, but when I call getListView() inside the receiver it hasn't got any child (though I've added to the adaptor in the oncreate method and I haven't loaded then using any thread at all). 在这种情况下,在onresume()中调用oncreate()方法后,接收方已注册,但是当我在接收方内部调用getListView()时,它没有任何子对象(尽管我已在oncreate方法中添加到适配器中,我还没有加载然后使用任何线程)。

Can anyone tell me why this is happening? 谁能告诉我为什么会这样吗?

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);
    }
}

Thanks 谢谢

First, I think we should go through some facts: 首先,我认为我们应该了解一些事实:

  • The activity will start drawing its content after the onResume() method is called but not "right after" 该活动将在调用onResume()方法之后开始绘制其内容,但不会“紧随其后”
  • After you call ListView.setListAdapter(...) the ListView only store the adapter object, at that time, there is no child view. 调用ListView.setListAdapter(...)之后,ListView仅存储适配器对象,此时,没有子视图。
  • A child view will be available after the ListView draw that child on screen (after Adapter.getView() is called) and the children view list will increase one by one each time the ListView add one more child view until ListView draws them all on screen. ListView在屏幕上绘制该子级后(调用Adapter.getView()之后),该子级视图将可用,并且每次ListView再添加一个子级视图时,子级视图列表将增加一,直到ListView在屏幕上全部绘制该子级。 。

And for your code, the reason why you can not get the children view list at the first time activity starts is "the ListView has not draw anything on screen". 对于您的代码,第一次活动启动时无法获得子视图列表的原因是“ ListView在屏幕上未绘制任何内容”。 Because the onReceive() method of the receiver is triggered before the ListView draws. 因为接收器的onReceive()方法是在ListView绘制之前触发的。

You can check that by yourself by overriding the adapter and show log to see the order those methods are called. 您可以通过覆盖适配器来自己检查,并显示日志以查看调用这些方法的顺序。 Here is my result: 这是我的结果:

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

Hope my answer can help you! 希望我的回答能对您有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM