android - 当 ListView 中的 View 值更新时,适配器未更新

标签 android listview android-listview android-arrayadapter android-viewholder

我正在使用 ListView 来显示一些我需要计算的元素的列表。我的 ListView 如下所示

enter image description here

当我单击加号和减号按钮或重置按钮时,值“3”会更新。这就是我在 CustomListViewAdapter 中实现此目的的方法

holder.plusButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            ViewGroup parent = (ViewGroup) v.getParent();
            TextView tv = (TextView) parent.findViewById(R.id.count);

            int count = Integer.parseInt((String) tv.getText());
            count++;
            tv.setText(String.valueOf(count));
            int currentVal = Integer.parseInt(totalCount.getText().toString());
            totalCount.setText(String.valueOf(currentVal + 1));
        }
    });

我使用 ViewHolder 模式。

现在的问题是,在我更新值后,它没有在适配器中更新。即,当我尝试循环适配器时,我仍然得到我最初设置的值 3,而不是更新后的值。我以正确的方式做这件事还是有更好的方法。如何确保适配器具有更新的值。

第二个问题:由于适配器没有更新,当我尝试从列表中检索值并将其发送到某个地方时,我会得到空指针

view = listView.getChildAt(i).findViewById(R.id.count);

用于列表中在屏幕上不可见的 View 。即,如果我有 10 个这样的行,则屏幕上只能看到 5 行,当我尝试访问第 6 行时,我会得到上述代码块的空指针。那么我应该如何访问 ListView 值?

编辑:我的 getView 方法源代码是

public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;
    Counter rowItem = getItem(position);

    LayoutInflater mInflater = (LayoutInflater) context
            .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);

    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.counter_list, null);
        holder = new ViewHolder();

        convertView.findViewById(R.id.parentLayoutRow).setBackgroundColor(Color.parseColor(rowItem.getPrimaryColor()));

        holder.resetButton = (Button) convertView.findViewById(R.id.buttonReset);
        holder.counterName = (TextView) convertView.findViewById(R.id.counterName);
        holder.counterDesc = (TextView) convertView.findViewById(R.id.counterDesc);
        holder.count = (TextView) convertView.findViewById(R.id.count);
        holder.minusButton = (Button) convertView.findViewById(R.id.buttonMinus);
        holder.plusButton = (Button) convertView.findViewById(R.id.buttonPlus);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.resetButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            ViewGroup parent = (ViewGroup) v.getParent();
            TextView tv = (TextView) parent.findViewById(R.id.count);

            int currentVal = Integer.parseInt(totalCount.getText().toString());
            totalCount.setText(String.valueOf(currentVal - Integer.parseInt(tv.getText().toString())));

            tv.setText(String.valueOf(0));
        }
    });
    holder.counterName.setText(rowItem.getName());
    holder.counterDesc.setText(rowItem.getDesc());
    holder.count.setText(String.valueOf(rowItem.getCount()));
    holder.resetButton.setBackgroundColor(Color.parseColor(rowItem.getButtonColor()));
    holder.minusButton.setBackgroundColor(Color.parseColor(rowItem.getButtonColor()));
    holder.minusButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            ViewGroup parent = (ViewGroup) v.getParent();
            TextView tv = (TextView) parent.findViewById(R.id.count);

            int count = Integer.parseInt((String) tv.getText());

            if (count > 0) {
                count--;
                tv.setText(String.valueOf(count));
                int currentVal = Integer.parseInt(totalCount.getText().toString());
                totalCount.setText(String.valueOf(currentVal - 1));
            } 
        }
    });
    holder.plusButton.setBackgroundColor(Color.parseColor(rowItem.getButtonColor()));
    holder.plusButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            ViewGroup parent = (ViewGroup) v.getParent();
            TextView tv = (TextView) parent.findViewById(R.id.count);

            int count = Integer.parseInt((String) tv.getText());
            count++;
            tv.setText(String.valueOf(count));
            int currentVal = Integer.parseInt(totalCount.getText().toString());
            totalCount.setText(String.valueOf(currentVal + 1));
        }
    });

    return convertView;
}

现在如何更新此函数中的适配器值holder.minusButton.setOnClickListener(new OnClickListener()

最佳答案

ListView 中的 View 不保留其状态。正如 ViewHolder 所示,它们在离开屏幕时会被丢弃,并在稍后重建:它们始终由适配器中的值驱动。

因此,您要做的就是在适配器中找到支持列表的条目并更新该条目,然后让 ListView 重绘本身。查看 ListView.getAdapter(),然后查看 Adapter.getItem()。您会注意到,没有 Adapter.setItem(),并且您无法更改现有 String 或 Integer 的值(它们是不可变的),因此您的列表项需要是包装该值的对象。或者您可以使用具有增量方法的 AtomicInteger。 然后,您需要调用 ListView.notifyDataSetChanged(),因为它不会检查包装对象内部。

关于android - 当 ListView 中的 View 值更新时,适配器未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29183411/

相关文章:

wpf - 更优雅的ListView重新查询

Android 在 ScrollView 中添加 ListView 并从 ListView 中删除滚动

java - 尝试打开/assets 中的 sqlite 文件时收到 "Could not open database"错误

带有光标适配器滚动问题的android ListView

android - 使用 espresso 和 ui automator 在 android studio 2.3 中生成测试覆盖率报告

android - 如何将 GridView 的选择模式设置为多个?

android - 将 Android 通知从 FLAG_ONGOING_EVENT 切换为可取消

android - 我的列表、 ScrollView 和按钮出错

java - 可以从 Android 应用程序中跳过轨道吗?

android - 如何删除 ListView 中的边框?