zoukankan      html  css  js  c++  java
  • Android 解决 adapter.notifyDataSetChanged() 不起作用

              
                  
                                               
      转载请注明出处:http://blog.csdn.net/like_program/article/details/52517119

    使用 Listview 的时候,给 adapter 的数据源 List 添加了新的数据,然后调用 adapter.notifyDataSetChanged(),发现 listview 并没有显示出新增的数据,但是遍历输出 List 中的元素,发现新增数据已经被添加到 List 中了,数据既然已经被添加到数据源中了,为什么 Listview 没有更新呢?
    上网,查书,查了半天,终于在《Android群英传》中找到答案:

      使用 adapter.notifyDataSetChanged() 时,必须保证传进 Adapter 的数据 List 是同一个 List
      而不能是其他对象,否则无法更新 listview。

    即,你可以调用 List 的 add(), remove(), clear(),addAll() 等方法,这种情况下,List 指向的始终是你最开始 new 出来的 ArrayList ,然后调用 adapter.notifyDataSetChanged() 方法,可以更新 ListView;但是如果你重新 new 了一个 ArrayList(重新申请了堆内存),那么这时候,List 就指向了另外一个 ArrayLIst,这时调用 adapter.notifyDataSetChanged() 方法,就无法刷新 listview 了。
    说了这么多,不如来写个小 Demo 来感受下:
    打开 Android Studio,新建一个 ListViewTest 项目。
    activity_main.xml 代码如下:
     
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.example.listviewtest.MainActivity">
        <Button
            android:id="@+id/btn_add_success"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="添加数据成功"/>
        <Button
            android:id="@+id/btn_add_fail"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="添加数据失败"/>
        <Button
            android:id="@+id/btn_delete"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="删除数据"/>
        <Button
            android:id="@+id/btn_clear"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="清空数据"/>
        <ListView
            android:id="@+id/listview"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        </ListView>
    </LinearLayout>
    12345678910111213141516171819202122232425262728293031323334353637383940
    布局文件很简单,从上至下,依次是 3 个按钮和一个 ListView。
    MainActivity.java 代码如下:
     
    package com.example.listviewtest;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.ArrayAdapter;
    import android.widget.Button;
    import android.widget.ListView;
    import android.widget.Toast;
    import java.util.ArrayList;
    import java.util.List;
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
        public static final String TAG = "MainActivity";
        /**
         * 添加成功 按钮
         */
        private Button btnAddSuccess;
        /**
         * 添加失败 按钮
         */
        private Button btnAddFail;
        /**
         * 删除数据 按钮
         */
        private Button btnDelete;
        /**
         * 清空数据 按钮
         */
        private Button btnClear;
        private ListView listView;
        /**
         * 适配器的数据源
         */
        private List<Integer> dataList;
        /**
         * 适配器
         */
        private ArrayAdapter adapter;
        /**
         * 添加的数据
         */
        private int addNumber = 3;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            // 实例化控件
            btnAddSuccess = (Button) findViewById(R.id.btn_add_success);
            btnAddFail = (Button) findViewById(R.id.btn_add_fail);
            btnDelete = (Button) findViewById(R.id.btn_delete);
            btnClear = (Button) findViewById(R.id.btn_clear);
            listView = (ListView) findViewById(R.id.listview);
            // 设置点击监听
            btnAddSuccess.setOnClickListener(this);
            btnAddFail.setOnClickListener(this);
            btnDelete.setOnClickListener(this);
            btnClear.setOnClickListener(this);
            // 初始化数据
            initData();
            // 创建适配器
            adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout
                    .simple_list_item_1, dataList);
            // 设置适配器
            listView.setAdapter(adapter);
        }
        /**
         * 初始化数据源
         */
        private void initData() {
            dataList = new ArrayList<>();
            for (int i = 0; i < 3; i++) {
                dataList.add(i);
            }
        }
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                // 如果点击的是 添加数据成功 按钮
                case R.id.btn_add_success:
                    // 添加数据 成功
                    dataList.add(addNumber);
                    adapter.notifyDataSetChanged();
                    Toast.makeText(MainActivity.this, "添加成功", Toast.LENGTH_SHORT).show();
                    Log.d(TAG, "数据源:" + dataList.toString());
                    break;
                // 如果点击的是 添加数据失败 按钮
                case R.id.btn_add_fail:
                    dataList = new ArrayList<>();
                    initData();
                    // 添加数据失败
                    dataList.add(addNumber);
                    adapter.notifyDataSetChanged();
                    Toast.makeText(MainActivity.this, "添加失败", Toast.LENGTH_SHORT).show();
                    Log.d(TAG, "数据源:" + dataList.toString());
                    break;
                // 如果点击的是 删除数据 按钮
                case R.id.btn_delete:
                    if (!dataList.isEmpty()) {
                        // 删除 list 最后一个数据
                        int deleteNumber = dataList.get(dataList.size() - 1);
                        dataList.remove(deleteNumber);
                        adapter.notifyDataSetChanged();
                        Toast.makeText(MainActivity.this, "删除数据", Toast.LENGTH_SHORT).show();
                        Log.d(TAG, "数据源:" + dataList.toString());
                    } else {
                        Toast.makeText(MainActivity.this, "已经没有数据了", Toast.LENGTH_SHORT).show();
                        Log.d(TAG, "数据源:" + dataList.toString());
                    }
                    break;
                // 如果点击的是 清空数据 按钮
                case R.id.btn_clear:
                    // 清空数据
                    dataList.clear();
                    adapter.notifyDataSetChanged();
                    Toast.makeText(MainActivity.this, "清空数据", Toast.LENGTH_SHORT).show();
                    Log.d(TAG, "数据源:" + dataList.toString());
                    break;
            }
        }
    }123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
    MainActivity.java 代码也很简单,给四个按钮加上了按键监听,然后让 ListView 显示了 3 个数字,接下来,我们先点击 添加数据成功,删除数据,清除数据 ,这 3 个按钮,看 adapter.notifyDataSetChanged() 能否正常工作。
     
    查看动态图,我们可以看到,点击这 3 个按钮,adapter.notifyDataSetChanged() 都可以正常工作,因为数据源始终是同一个 List,修改的只是 List 中的数据。
    我们重新启动下 ListViewTest,再来看看点击 添加数据失败 按钮,adapter.notifyDataSetChanged() 能否正常工作。
    查看 Logcat ,我们发现,数据源中的数据已经更新了:
     
     
    但是查看动态图,我们可以看到,点击按钮,ListView 并没有更新数据,这时因为重新 new 了一个 ArrayList(重新申请了堆内存),那么这时候,List 就指向了另外一个 ArrayLIst,而要更新 ListView,必须保证传进 Adapter 的数据 List 是同一个 List 而不能是其他对象,所以 ListView 就无法更新了。
     
  • 相关阅读:
    URAL1966 Cipher Message 3
    hdu5307 He is Flying
    UVA12633 Super Rooks on Chessboard
    spoj-TSUM Triple Sums
    bzoj3160 万径人踪灭
    bzoj2194 快速傅立叶之二
    FFT NTT 模板
    NOI2009 植物大战僵尸
    最长k可重线段集问题
    最长k可重区间集问题
  • 原文地址:https://www.cnblogs.com/xgjblog/p/13042321.html
Copyright © 2011-2022 走看看