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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM