创建 RecyclerView 适配器后,会返回有关我的 View 持有者的警告。我读过this question并理解了一点,但不清楚 return viewHolder;
中的 viewHolder
实例应该替换为什么。
Expression might evaluate to null but is returned by the method declared as @NotNull
public class MyRVAapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final static int TYPE_EXPANDABLE = 1, TYPE_NONEXPANDABLE = 2;
private ArrayList callSMSFeed = new ArrayList();
private Context context;
public MyRVAapter(Context context){
this.context = context;
}
public void setCallSMSFeed(List<Object> callSMSFeed){
this.callSMSFeed = (ArrayList) callSMSFeed;
}
@Override
public int getItemViewType(int position) {
if (callSMSFeed.get(position) instanceof Phonecall) {
return TYPE_EXPANDABLE;
} else if (callSMSFeed.get(position) instanceof SMSmessage) {
return TYPE_NONEXPANDABLE;
}
return -1;
}
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, final int position) {
int viewType=holder.getItemViewType();
switch (viewType){
case TYPE_EXPANDABLE:
Phonecall call = (Phonecall) callSMSFeed.get(position);
((CallViewHolder)holder).showCallDetails(call);
break;
case TYPE_NONEXPANDABLE:
SMSmessage sms = (SMSmessage)callSMSFeed.get(position);
((SMSViewHolder)holder).showSmsDetails(sms);
break;
}
}
@Override
public int getItemCount(){return callSMSFeed.size();}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
int layout;
RecyclerView.ViewHolder viewHolder;
switch (viewType){
case TYPE_EXPANDABLE:
layout = R.layout.cardview_a;
View callsView = LayoutInflater
.from(parent.getContext())
.inflate(layout, parent, false);
viewHolder = new CallViewHolder(callsView);
break;
case TYPE_NONEXPANDABLE:
layout = R.layout.cardview_b;
View smsView = LayoutInflater
.from(parent.getContext())
.inflate(layout, parent, false);
viewHolder = new SMSViewHolder(smsView);
break;
default:
viewHolder = null;
break;
}
return viewHolder;
}
}
最佳答案
我喜欢@TheWanderer 的答案,但我想添加另一个答案,以强调我认为会让您的生活更轻松的一些内容。
与ListView
不同,RecyclerView
不关心从getItemViewType()
返回什么值;只要您从此方法返回不同的值,RecyclerView
就很高兴。这允许您使用布局资源 id 作为返回值,这意味着您无需定义自己的常量!
@Override
public int getItemViewType(int position) {
Object obj = callSMSFeed.get(position);
if (obj instanceof Phonecall) {
return R.layout.cardview_a;
} else if (obj instanceof SMSmessage) {
return R.layout.cardview_b;
}
throw new IllegalStateException("item at position " + position + " is not a Phonecall or SMSmessage: " + obj);
}
这里我们返回R.layout.cardview_a
而不是TYPE_EXPANDABLE
;两者都是 int 类型,但现在我们可以让 Resources 框架为我们定义它们。
如果我们遇到的对象
不是电话
或短信
,我们也会抛出异常,以便我们立即知道有一个案子我们需要处理。这种异常应该只有开发人员犯错误时才会看到;该应用程序永远不会对用户造成崩溃,因为您将在发布该应用程序之前继续修复崩溃问题。
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View itemView = inflater.inflate(viewType, parent, false);
switch (viewType) {
case R.layout.cardview_a:
return new CallViewHolder(itemView);
case R.layout.cardview_b:
return new SMSViewHolder(itemView);
default:
throw new IllegalArgumentException("unexpected viewType: " + viewType);
}
}
因为我们从 getItemViewType()
返回布局 ID,所以我们不必担心从我们自己的常量转换为 R.layout
值;我们可以直接膨胀 viewType
。不过,我们仍然需要 switch
语句来了解要返回哪种类型的 ViewHolder
。
再次,我们在这里抛出了一个异常,以防我们传递了一个我们不期望的viewType
。这种情况“不会发生”,但如果发生了,问题出在哪里就会非常清楚,并且很容易修复。
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
int viewType = holder.getItemViewType();
switch (viewType) {
case R.layout.cardview_a:
Phonecall call = (Phonecall) callSMSFeed.get(position);
((CallViewHolder) holder).showCallDetails(call);
break;
case R.layout.cardview_b:
SMSmessage sms = (SMSmessage) callSMSFeed.get(position);
((SMSViewHolder) holder).showSmsDetails(sms);
break;
default:
throw new IllegalArgumentException("unexpected viewType: " + viewType);
}
}
这里唯一的区别是用 switch
内的布局 id 替换常量。没什么大不了。当然,如果我们得到一些我们没有预料到的东西,我们就会崩溃。
另请注意,我已从参数中删除了 final
关键字。尽管编译器很乐意让您添加它们,但您不应该这样做。由于使用 notifyItemInserted()
等方法,ViewHolder
的位置可能会随着时间的推移而发生变化,而无需重新绑定(bind)。处理这个问题超出了您的问题范围,但需要指出。
关于java - 表达式的计算结果可能为 null,但由声明为 @NotNull 的方法返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52744611/