Adapter的notifyDataSetChange无效的问题

前段时间遇到一个问题,那就是在Activity中通过构造函数实例化自定义Adapter并setAdapter()后,再修改数据源,赋值后调用notifyDataSetChange()方法,然并卵的问题!看了很久的源码想从观察者模式入手搞清楚这是为什么?结果并没有什么发现,但是对Java的设计模式模式倒是有了一定的了解。

后来想看一下是不是刷新的时候数据源的问题,于是做了如下这个测试。

首先是一个简单的DEMO!

我的思路如下:

1.在Adapter中定义一个刷新的方法在方法里面调adapter的notifyDataSetchange()方法,并打印出当前的数据源的hashCode。

2.在Adapter中定义一个setParams()方法给Adapter的数据源设值。

3.在Activity中添加一个Button,在点击事件中调用Adapter中我们自己写的刷新方法刷新数据并打印Activity中的数据源的hashCode。


下面上代码:

Activity:

public class SlidingListActivity extends AppCompatActivity {

    private Button btnTest;
    private ListView lvSliding;
    private SlidingListAdapter adapter;
    private List<String> data;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sliding_list);

        initView();
    }


    private void initView(){
        btnTest = (Button) findViewById(R.id.button);
        btnTest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //data = getParams2();
                //adapter.setParams(data);
                //打印数据源的hashCode
                Log.i("SlidingListActivity", "data.hashCode: "+data.hashCode());
                //调用adapter中自定义的数据刷新方法
                adapter.myNotifyDataSetChange();
            }
        });
        lvSliding = (ListView)findViewById(R.id.sliding_list);
        data = getParams();
        adapter = new SlidingListAdapter(SlidingListActivity.this,data);
        lvSliding.setAdapter(adapter);

    }

    /**
     * 数据源一
     * @return
     */
    private List<String> getParams(){
        List<String> params = new ArrayList();
        for (int i=0;i<30;i++){
            params.add("ITEM: "+i);
        }
        return params;
    }


    /**
     * 数据源二
     * @return
     */
    private List<String> getParams2(){
        List<String> params = new ArrayList();
        for (int i=0;i<30;i++){
            params.add("ITEM2: "+i);
        }
        return params;
    }
}


Activity的XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_sliding_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.xuzhenhao.myapplication.SlidingListActivity">

    <ListView
        android:id="@+id/sliding_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none">

    </ListView>

    <Button
        android:text="刷"
        android:textColor="#4C8BF5"
        android:textSize="18sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true"
        android:layout_marginStart="313dp"
        android:layout_marginBottom="30dp"
        android:id="@+id/button" />

</RelativeLayout>


Adapter:

public class SlidingListAdapter extends BaseAdapter {



    private List<String> params;
    private LayoutInflater mLayoutInflater;

    public SlidingListAdapter(Context mContext, List<String> params) {
        this.params = params;
        mLayoutInflater = LayoutInflater.from(mContext);
    }

    /**
     * 给Adapter的成员变量设值
     * @param params
     */
    public void setParams(List<String> params){
        this.params = params;
    }

    /**
     * 自定义数据刷新
     */
    public void myNotifyDataSetChange(){
        //打印数据源的hashCode
        Log.i("SlidingListAdapter","params.hashCode: "+params.hashCode());
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return params.size();
    }

    @Override
    public Object getItem(int position) {
        return params.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null){
            holder = new ViewHolder();
            convertView = mLayoutInflater.inflate(R.layout.item_sliding_list,parent,false);
            holder.tvDrawerItem = (TextView) convertView.findViewById(R.id.item_content);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder) convertView.getTag();
        }
            holder.tvDrawerItem.setText(params.get(position));
        return convertView;
    }


    private class ViewHolder{

        TextView tvDrawerItem;
    }
}

运行后demo的就是长这样了


现在先点击一下按钮打印一下hashCode

如图所示,Activity和Adapter中的hashCode都是一样的


再将数据源更换后点击刷新按钮,我们发现ListView中的数据并没有刷新

btnTest = (Button) findViewById(R.id.button);
btnTest.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
           //新的数据源
           data = getParams2();
           //adapter.setParams(data);
           //打印数据源的hashCode
           Log.i("SlidingListActivity", "data.hashCode: "+data.hashCode());
           //调用adapter中自定义的数据刷新方法
           adapter.myNotifyDataSetChange();
       }
   });



而Activity和Adapter中打印出的hashcode也不一样,如下图所示:



那么如果调用我们在Adapter中定义的setParams()方法对Adapter中的成员变量(数据源)赋值后会怎样呢?

btnTest = (Button) findViewById(R.id.button);
btnTest.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //新的数据源
        data = getParams2();
        //调用Adapter的方法对Adapter的成员变量赋值
        adapter.setParams(data);
        //打印数据源的hashCode
        Log.i("SlidingListActivity", "data.hashCode: "+data.hashCode());
        //调用adapter中自定义的数据刷新方法
        adapter.myNotifyDataSetChange();
    }
});
这时我们重新点击刷新按钮发现ListView被刷新了



再看看Activity和adapter中的hashCode,发现是一样的,如下图所示:



所以有很多像我一样刚入门的Android开发人员会有这样的疑问“为啥我改了数据源,调用notifyDataSetChange()方法会没有效果!”,根本原因就是Adapter中的数据源压根就没有被改变!!!




  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值