更改数组列表时,带有 ArrayList 和 ListView 的 Android 数组适配器不会更新

Posted

技术标签:

【中文标题】更改数组列表时,带有 ArrayList 和 ListView 的 Android 数组适配器不会更新【英文标题】:Android Array Adapter with ArrayList and ListView not updating when the arraylist is changed 【发布时间】:2012-10-27 19:37:43 【问题描述】:

我有一个 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,notifyDataSetChanged 仅在您使用适配器上的 addinsertremoveclear 函数时才有效。

    使用 clear 清除适配器 - arrayAdapter.clear() 使用 Adapter.addAll 并添加新形成的列表 - arrayAdapter.addAll(deviceList) 调用 notifyDataSetChanged

替代方案:

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

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

【讨论】:

这不是真的,请参阅@Laura 回复【参考方案2】:

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

Slartibartfast 关于notifyDataSetChanged() 仅在适配器上调用addinsertremoveclear 时有效的解释不正确。

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

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

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

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

希望这对某人有所帮助!

【讨论】:

【参考方案3】:

您的方法 addDevice 导致无限循环。不要像您在这里所做的那样从自身调用方法:

deviceList = addDevice();

【讨论】:

打扰了,这只是我的一个错字...抱歉造成混乱 您可以发布您的 createNewDeviceList(),它可能不会在您的列表中添加任何新内容,而是使用与原始元素和顺序相同的元素和顺序创建新列表

以上是关于更改数组列表时,带有 ArrayList 和 ListView 的 Android 数组适配器不会更新的主要内容,如果未能解决你的问题,请参考以下文章

没有得到相同的 ArrayList 顺序

带有ajax更新的Jqueryui可排序列表

java中ArrayList和LinkedList的区别

关于JAVA核心技术(卷一)读后的思考(泛型数组列表的讨论)

在Java中,ArrayList与数组如何相互转换,写出例子

如何在Java中创建数组列表