昨天出于一些原因改写了之前一个项目的Listview的数据获取方式,结果数据是有的,而ListView却死活没有将数据显示出来。调试了很久,把数据一个一个Log出来,怎么看都觉得构造Adapter的list里面是有数据的。后来才发现自己犯了一个低级错误,这跟Java值传递方式有关,所以基础要扎实的原因就是这这么来的。
我们知道在使用自定义的Adapter的时候一般是需要在构造方法内传一个集合作为数据来源。比如下面是自定义的CommentAdapter的构造函数:
public CommentAdapter(List<CommentEntity> cmList) {
cmDataList = cmList;
}
由于需要从服务器加载数据,我先用一个空的commentDataList构造Adapter,等从服务器加载完数据后再调用notifyDataChanged()来刷新数据显示。
在Activity先这么写:
第一步:
mAdapter = new CommentAdapter(commentDataList); //空的commentDataList
mListView.setAdapter(mAdapter);
这一以来,CommentAdapter中的cmDataList这个变量就指向了Activity中的commentDataList这个变量所指向的内存空间。
从服务器拉取数据,假设方法为getCommentListFromServer(),返回一个List,低级错误就是这么来的,我在Activity中是这么写的:
第二步:
commentDataList = getCommentListFromServer();
以为这样写,调用notifyDataChanged()的时候会刷新ListView那就大错特错。
首先必须明确的是,Java只有传值,基本数据类型传的值是内容(名副其实的传值), 对象传的值是对象的地址(传值传的值是一个地址).
操纵方法体中的参数, 操纵的是另一个有自己内存空间的变量, 而不是我们传入的变量, 但是这两个变量可以指向同一个对象实体。
在第一步之后,cmDataList,与commentDataList都指向的是同一个List的内存空间,但是第二步之后,commentDataList的指向改变为getCommentListFromServer()所返回的List的内存空间(这个List是有数据的),但是cmDataList的指向依然是之前的List的内存空间(空的List),也就是说Adapter所绑定的依然是一个空的List, 当然不论怎么刷新都不会有数据出来的。
正确的姿势:
List<Comment> tempList = getCommentListFromServer();// 一个暂存的数据的list
commentDataList.addAll(tempList);//这样改变的就是内存空间的内容,而不是变量的指向