【问题标题】:Strange problem with broadcast receiver in AndroidAndroid中广播接收器的奇怪问题
【发布时间】:2010-07-30 08:47:38
【问题描述】:

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

谢谢

【问题讨论】:

    标签: java android listview broadcastreceiver


    【解决方案1】:

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

    • 活动将在调用 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
    

    希望我的回答能帮到你!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多