带有 ArrayList 和 ListView 的 Android Array Adapter 在数组列表更改时不会更新

我有一个Android应用程序,其屏幕由ListView组成,我用它来显示设备列表。这些设备保存在阵列中。

我正在尝试使用ArrayAdapter在列表中显示屏幕上数组中的内容。

当我第一次加载 SetupActivity 类时,它可以工作,但是,在 addDevice() 方法中可以添加新设备,这意味着保存设备的数组已更新。

我正在使用 notifyDataSetChanged(), 它应该更新列表,但它似乎不起作用。

public class SetupActivity extends Activity
{   
    private ArrayList<Device> deviceList;

    private ArrayAdapter<Device> arrayAdapter;

    private ListView listView;

    private DevicesAdapter devicesAdapter;

    private Context context;

    public void onCreate(Bundle savedInstanceState)  //Method run when the activity is created
    {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.setup);  //Set the layout

        context = getApplicationContext();  //Get the screen

        listView = (ListView)findViewById(R.id.listView);

        deviceList = new ArrayList<Device>();

        deviceList = populateDeviceList();  //Get all the devices into the list

        arrayAdapter = new ArrayAdapter<Device>(this, android.R.layout.simple_list_item_1, deviceList);

        listView.setAdapter(arrayAdapter);  
    }

    protected void addDevice()  //Add device Method (Simplified)
    {
        deviceList = createNewDeviceList();    //Add device to the list and returns an updated list

        arrayAdapter.notifyDataSetChanged();    //Update the list
}
}

有人能看到我哪里错了吗?


答案 1

对于 ArrayAdapter,仅当您在适配器上使用 、 、 和 函数时才有效。notifyDataSetChangedaddinsertremoveclear

  1. 使用清除来清除适配器 -arrayAdapter.clear()
  2. 使用 Adapter.addAll 并添加新形成的列表 -arrayAdapter.addAll(deviceList)
  3. 呼叫通知数据集已更改

选择:

  1. 在形成新的设备列表后重复此步骤 - 但这是多余的

    arrayAdapter = new ArrayAdapter<Device>(this, android.R.layout.simple_list_item_1, deviceList);
    
  2. 创建从 BaseAdapter 和 ListAdapter 派生出来的自己的类,为您提供更大的灵活性。这是最推荐的。

答案 2

虽然接受的答案解决了问题,但对原因的解释是不正确的,因为这是一个重要的概念,我想我会尝试澄清。

Slartibartfast 的解释(仅在适配器上调用 、 、 或)时才有效,这是不正确的。notifyDataSetChanged()addinsertremoveclear

该方法的解释是正确的,如果设置为true(默认情况下),则当发生这四个操作中的任何一个时,它将自动调用。setNotifyOnChange()notifyDataSetChanged()

我认为海报混淆了这两种方法。 本身没有这些限制。它只是告诉适配器它正在查看的列表已更改,并且列表的更改实际发生方式并不重要。notifyDatasetChanged()

虽然我看不到你的源代码,但我猜你的问题来自这样一个事实,即你的适配器引用了你创建的原始列表,然后你在 中创建了一个新列表,并且由于适配器仍然指向旧列表,因此它看不到更改。createNewDeviceList()createNewDeviceList()

提到的解决方案 slartibartfast 之所以有效,是因为它清除了适配器,并专门将更新后的列表添加到该适配器。因此,您不会遇到适配器指向错误位置的问题。

希望这有助于某人!


推荐