概述
最近发现recyclerview的一个异常,其他博客写的错的乱七八糟,在此纠正一下这个异常:
Attempt to write to field 'int android.support.v7.widget.RecyclerView$ViewHolder.mItemViewType' on a null object reference
at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:5555)
....
首先教大家如何看这种没有报错行的崩溃日志:
1.打开崩溃的最后一行RecyclerView$Adapter.createViewHolder(由于电脑api版本和手机api版本可能不同,报错行号不一定是对的,自己参考报错信息ViewHolder.mItemViewType找到对应的行号)
public final VH createViewHolder(ViewGroup parent, int viewType) {
TraceCompat.beginSection(TRACE_CREATE_VIEW_TAG);
final VH holder = onCreateViewHolder(parent, viewType);
holder.mItemViewType = viewType;//可以看出是这行崩溃导致的
TraceCompat.endSection();
return holder;
}
2.空指针异常知道吧:接着就看holder怎么是null的
3.onCreateViewHolder我就不用多解释了吧
4.检查自己的onCreateViewHolder肯定有返回null的情况
有的人可能很费解:返回null是因为自己知道这是一个不可能出现的类型,rv是不是有bug?
在这个崩溃日志上我可以肯定的告诉你,肯定是你的代码问题
如下我列出最常见的错误代码:
1.先看看adapter类,有人会问:加了高大上的super做容错(super.getItemViewType是0写不写没啥用)这样写有错吗?
@Override
protected BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType, LayoutInflater inflater) {
switch (viewType) {
case TYPE_HEADER:
return new XXViewHolder(inflater.inflate(R.layout.vw_header, parent, false));
case TYPE_FOTTER:
return new YYViewHolder(inflater.inflate(R.layout.frag_skintest1, parent, false));
default:
return null;
}
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return TYPE_HEADER;
} else if (position<=mList.size()){
return TYPE_FOTTER;
}
return super.getItemViewType(position);
}
2.这样写肯定也没错(勉强赞同?),但是下面的代码就是问题了
public void httpData(){
mList.clear();
HttpUtils.postDialog(this,"",//网络请求框架
MapUtils.getInstance(),
DataBean.class,
new OKHttpListener<DataBean>() {
@Override
public void onSuccess(DataBean bean) {//成功回调
mList.addAll(bean.data);
mAdapter.notifyDataSetChanged();
}
});
}
很多人都喜欢在请求之前去clear自己的list,然后在网络请求完成之后再addAll,但是:
你在请求网络期间rv是不会每次都调用getItemCount的,这时候rv会认为count还是原来的(比如100)。
这段时间如果rv去getItemViewType(99),但你已经把你的list对象clear了,得到的结果自然是0了。
然后rv去拿这个0去onCreateViewHolder,null就此产生了
3.正确的写法是:每次list发生变化的时候都应该刷新adapter来告诉rv数据发生变化了
public void httpData(){
HttpUtils.postDialog(this,"",
MapUtils.getInstance(),
DataBean.class,
new OKHttpListener<DataBean>() {
@Override
public void onSuccess(DataBean bean) {
mList.clear();
mList.addAll(bean.data);
mAdapter.notifyDataSetChanged();
}
});
}
或者你也可以先clear,然后立即notify,等网络请求完成addAll,然后立即notify
4.还有比如getItemViewType和onCreateViewHolder的type不对应等其他问题(博主的脑洞也是有限的)。
首先找到可疑的位置,多debug就明白了
结论:
1.要学会正确的看错误日志
2.数据改变,adapter要及时刷新
3.不要看到未知错误就度娘,要学会debug,就算什么头绪都没有,挨个打断点最终也能找出问题
转载请注明出处:王能的博客https://blog.csdn.net/weimingjue/article/details/79140697
最后
以上就是仁爱铃铛为你收集整理的纠正:Android Attempt to write to field 'int android.support.v7.widget.RecyclerView$ViewHolder...的全部内容,希望文章能够帮你解决纠正:Android Attempt to write to field 'int android.support.v7.widget.RecyclerView$ViewHolder...所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复