Android 解决 adapter.notifyDataSetChanged() 不起做用

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

使用 Listview 的时候,给 adapter 的数据源 List 添加了新的数据,而后调用 adapter.notifyDataSetChanged(),发现 listview 并无显示出新增的数据,可是遍历输出 List 中的元素,发现新增数据已经被添加到 List 中了,数据既然已经被添加到数据源中了,为何 Listview 没有更新呢?android

上网,查书,查了半天,终于在《Android群英传》中找到答案:app

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

即,你能够调用 List 的 add(), remove(), clear(),addAll() 等方法,这种状况下,List 指向的始终是你最开始 new 出来的 ArrayList ,而后调用 adapter.notifyDataSetChanged() 方法,能够更新 ListView;可是若是你从新 new 了一个 ArrayList(从新申请了堆内存),那么这时候,List 就指向了另一个 ArrayLIst,这时调用 adapter.notifyDataSetChanged() 方法,就没法刷新 listview 了。布局

说了这么多,不如来写个小 Demo 来感觉下:this

打开 Android Studio,新建一个 ListViewTest 项目。spa

activity_main.xml 代码以下:.net

<?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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

布局文件很简单,从上至下,依次是 3 个按钮和一个 ListView。code

MainActivity.java 代码以下:xml

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;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139

MainActivity.java 代码也很简单,给四个按钮加上了按键监听,而后让 ListView 显示了 3 个数字,接下来,咱们先点击 添加数据成功,删除数据,清除数据 ,这 3 个按钮,看 adapter.notifyDataSetChanged() 可否正常工做。

success

查看动态图,咱们能够看到,点击这 3 个按钮,adapter.notifyDataSetChanged() 均可以正常工做,由于数据源始终是同一个 List,修改的只是 List 中的数据。

咱们从新启动下 ListViewTest,再来看看点击 添加数据失败 按钮,adapter.notifyDataSetChanged() 可否正常工做。

查看 Logcat ,咱们发现,数据源中的数据已经更新了:

logcat

fail

可是查看动态图,咱们能够看到,点击按钮,ListView 并无更新数据,这时由于从新 new 了一个 ArrayList(从新申请了堆内存),那么这时候,List 就指向了另一个 ArrayLIst,而要更新 ListView,必须保证传进 Adapter 的数据 List 是同一个 List 而不能是其余对象,因此 ListView 就没法更新了。

源码下载