Android viewpager notifyDataSetChanged导致IllegalStateException

时间:2014-07-25 06:36:15

标签: android android-viewpager upnp fragmentpageradapter android-pageradapter

使用cling库进行upnp发现。每当deviceDiscovered启动时,调用以下代码来更新设备列表,因此调用notifyDataSetChanged的{​​{1}}

ViewPager

字段声明

public void deviceAdded(Registry registry, Device device) {
        // TODO Auto-generated method stub
        super.deviceAdded(registry, device);

        String name = device.getDisplayString();
        String manufac = device.getDetails().getManufacturerDetails()
                .getManufacturer();
        if (!manufac.contains("Microsoft")) {
            if (!deviceNames.contains(name)) {
                if (!devices.contains(device)) {
                    devices.add(device);
                    deviceNames.add(name);
                    Log.e(TAG,"\t\tdevice.size() = "+String.valueOf(devices.size()));
                //  Log.e(TAG,"Calling notify runnable after adding device "+deviceNames.get(deviceNames.size()-1));
                    runOnUiThread(notifyAdapterDataChanged);
                }

            }
        }
}

ArrayList/*CopyOnWriteArrayList*/<Device> devices; ArrayList/*CopyOnWriteArrayList*/<String> deviceNames; 是可运行的,如下所示

notifyAdapterDataChanged

获得以下异常

@Override
        public void run() {
            if(adapter != null){
                adapter.notifyDataSetChanged();
             }
       }

3 个答案:

答案 0 :(得分:3)

首先:在次之后,您将项目添加到适配器中引用的列表中,您必须调用notifyDataSetChanged

在UI线程执行notifyDataChanged之前添加第二个项目时,通常会发生这种情况。您可以通过使用适配器添加项目来防止这种情况。

如果您希望将项目直接添加到列表而不是适配器,则可以使用互斥锁等待runOnUIThread完成 - 如下所示:

final Semaphore mutex = new Semaphore(0);
runOnUiThread(new Runnable() {
    @Override
    public void run() {
        adapter.notifyDataSetChanged();
        mutex.release();
    }
});

try {
    // wait for the line mutex.release(); to be executed
    mutex.acquire();
} catch (InterruptedException e) {
    e.printStackTrace();
}

现在,如果您将一个项目添加到列表并从UI线程开始,则添加项目的线程将等待(通过互斥锁)UI线程完成并通知适配器。这样就可以防止在更新适配器之前附加项目滑入列表的情况。

编辑:另一种解决方案是在UI线程中添加项目。在你的情况下是这样的:

runOnUiThread(new Runnable() {
        @Override
        public void run() {
            devices.add(device);
            deviceNames.add(name);
            adapter.notifyDataSetChanged();
        }
    });

这样您就可以避免使用mutex,同时每adapter.notifyDataSetChanged();次调用只会添加一项。

答案 1 :(得分:0)

如果你看这里:https://stackoverflow.com/a/5092426/1235505

引用:

  

对于ArrayAdapter,只有在适配器上使用add(),insert(),remove()和clear()时,notifyDataSetChanged才有效。

因此,如果您手动将设备添加到适配器中的集合中,则修改数据后可能会出现异常。

我无法确定您是否已经在问题中使用这些方法,如果您这样做,请在下次向我们展示字段声明。

答案 2 :(得分:0)

如果您出于某种原因离开了您的活动(例如通过Intent转到其他应用程序),您必须在您的活动中添加以下行。

   android:configChanges="keyboardHidden|orientation|screenSize"