转载请注明出处: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>

布局文件很简单,从上至下,依次是 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;        }    }}

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 就无法更新了。

源码下载

更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. 一句话锁定MySQL数据占用元凶
  3. 数据结构基础知识核心归纳(二)
  4. Android(安卓)自动更新 + IIS7 添加APK mime
  5. Android(安卓)Jetpack之LiveData源码分析
  6. Android(安卓)联系人数据库介绍以及对联系人的基本操作
  7. android:SQLiteOpenHelper 与 greenDao 数据库操作
  8. SQlite数据库框架:LitePal
  9. android 给动画添加结束监听事件

随机推荐

  1. T-SQL 查询语句的执行顺序解析
  2. 利用sys.sysprocesses检查SqlServer的阻
  3. 学习SQL语句(强大的group by与select fro
  4. SqlServer 基础知识 数据检索、查询排序
  5. sql 常用技巧整理
  6. SQL Server Table中XML列的操作代码
  7. sqlserver 中时间为空的处理小结
  8. 通过分析SQL语句的执行计划优化SQL
  9. sql数据库批量处理脚本
  10. sqlserver 存储过程动态参数调用实现代码