【错误记录】Android中,notifyDataSetChanged()不能正确更新listView问题

问题简介

在学习开发android过程中,遇到了一个似乎很普遍的问题。当我们在初始化通过adapter将Listview和对应的Arraylist 数据data绑定时,在后面的data更新后,理论上使用adapter.notifyDataSetChanged()方法就可以让adapter自动更新Arraylist列表,但是实际上我们在对data更新之后,并不能完成对视图中ListView的更新,问bing问了一通也没问出啥解决方法,最后还是查了半天才明白咋回事。。。

结论

解决方法① 可能是最有效的解决方法
将更新后的数据data和视图ListView与适配器adapter重新绑定
即调用绑定时的方法:

data=new_data;//有数据更新
adapter=new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_1,data);
listView.setAdapter(adapter);

解决方法②
对于Arraylist类型的数据data,只在原对象上修改,不能重新赋值,因为重新赋值实质上改变了data所指向的对象,导致adapter的绑定出现问题,这可能也是notifyDataSetChanged()一个使用条件。

data.add("123");//数据更新
//不能data=new_data;
adapter.notifyDataSetChanged();

下面可以不用看啦

代码分析

package com.example.test.ui.slideshow;

import static java.lang.System.out;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;

import com.example.test.R;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;

public class SlideshowFragment extends Fragment implements View.OnClickListener {

    //private Integer[] data={1,2,3,5,65,6,7,4,4,6,44,33,9,6,6,49491,85,5,6,2,25,51,25,20,2};
    private String[] ori_data={"test_keyword1","test_keyword2","test_keyword3","test_keyword4","test_keyword1"
            ,"test_keyword2","test_keyword3","test_keyword4","test_keyword1","test_keyword2","test_keyword3"
            ,"test_keyword4","test_keyword1","test_keyword2","test_keyword3","test_keyword4"};
    private ArrayList<String> data = new ArrayList<>(Arrays.asList(ori_data));
    private ArrayAdapter<String> adapter=null;
    private ListView listView;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View view =inflater.inflate(R.layout.fragment_email,container,false);
        listView=(ListView) view.findViewById(R.id.list_email);
        adapter=new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_1,data);
        listView.setAdapter(adapter);

        //单击每个item进行编辑
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                edit_item(position,adapter);
            }
        });

        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                del_item(position,adapter);
                return true; // 返回true表示已经处理了长按事件,不会触发单击事件
            }
        });



        view.findViewById(R.id.btn_add).setOnClickListener(this);
        view.findViewById(R.id.btn_sync).setOnClickListener(this);
        view.findViewById(R.id.btn_save).setOnClickListener(this);
        view.findViewById(R.id.btn_submit).setOnClickListener(this);
        return view;
    }

    @Override
    public void onClick(View v) {
        if(v.getId()==R.id.btn_add){
            edit_item(data.size(), adapter);
        }
        else if(v.getId()==R.id.btn_sync){
            //从服务器将数据同步到客户端
            data=load();
            adapter=new ArrayAdapter<String>(getActivity(),
                    android.R.layout.simple_list_item_1,data);
            listView.setAdapter(adapter);
            Toast.makeText(getActivity(),"已成功加载",Toast.LENGTH_SHORT).show();
        }
        else if(v.getId()==R.id.btn_save){
            save();
            Toast.makeText(getActivity(),"已成功保存",Toast.LENGTH_SHORT).show();
        }
        else if(v.getId()==R.id.btn_submit){

        }
    }

    private void save(){
        FileOutputStream out=null;
        BufferedWriter writer=null;
        try{
            out =getActivity().openFileOutput("test_datasave.txt", Context.MODE_PRIVATE);
            writer=new BufferedWriter(new OutputStreamWriter(out));
            for (String str : data) {
                writer.write(str);
                writer.write('\n');
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if(writer!=null){
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private ArrayList<String> load(){
        ArrayList<String> data=new ArrayList<>();
        FileInputStream in =null;
        BufferedReader reader=null;
        try{
            in=getActivity().openFileInput("test_datasave.txt");
            reader=new BufferedReader(new InputStreamReader(in));
            String line="";
            while((line=reader.readLine())!=null){
                data.add(line.toString());
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Toast.makeText(getActivity(),"未找到文件",Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(reader!=null){
                try{
                    reader.close();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
        }
        return data;
    }

    //用于弹出dialog 并修改其中的某一项
    private void edit_item(int postition,ArrayAdapter<String> adapter){
        AlertDialog.Builder dialog=new AlertDialog.Builder(getActivity());
        dialog.setTitle("编辑");

        EditText editText=new EditText(getActivity());
        editText.setHint("请键入新的关键词");
        dialog.setView(editText);

        dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                final String inputText=editText.getText().toString();
                if(data.size()==postition){
                    data.add(inputText);
                }
                else data.set(postition,inputText);
                adapter.notifyDataSetChanged();
            }
        });
        dialog.show();
    }

    //用于弹出一个dialog,用于确认删除其中的某一项
    private void del_item(int postition,ArrayAdapter<String> adapter){
        AlertDialog.Builder dialog=new AlertDialog.Builder(getActivity());
        dialog.setTitle("删除");
        dialog.setMessage("确认删除这一项?");
        dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                data.remove(postition);
                adapter.notifyDataSetChanged();
            }
        });
        dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        dialog.show();
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Android 开发ListView 是常用的列表控件,而 Adapter 则是 ListView 显示列表数据的适配器。当数据源改变时,我们需要调用 Adapter 的 notifyDataSetChanged() 方法来通知 ListView 更新数据。不过有时候,我们会发现调用 notifyDataSetChanged() 方法后,ListView 并没有更新数据,这通常是由以下几个原因造成的: 1. 数据源没有更新 在调用 notifyDataSetChanged() 方法之前,需要先确保数据源已经更新了。如果数据源没有更新,调用 notifyDataSetChanged() 方法也不会更新 ListView 显示的数据。 2. Adapter 对象没有重新设置 如果使用的是同一个 Adapter 对象,那么需要重新设置 Adapter 对象才能更新 ListView 显示的数据。可以通过 setAdapter() 方法重新设置 Adapter 对象。 3. ListView 没有重新绘制 当调用 notifyDataSetChanged() 方法后,ListView 并不会立即重新绘制,而是等到系统认为需要重新绘制时才会更新。可以通过调用 invalidate() 方法让 ListView 立即重新绘制。 4. 数据源和 Adapter 对象不匹配 如果数据源和 Adapter 对象不匹配,即数据源的数据类型和 Adapter 的数据类型不一致,调用 notifyDataSetChanged() 方法也无法更新 ListView 显示的数据。 综上所述,如果在 ListView 调用 notifyDataSetChanged() 方法无效,可以先检查数据源是否更新,是否重新设置 Adapter 对象,是否调用了 invalidate() 方法以及数据源和 Adapter 对象是否匹配。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值