Strange NullPointerException in my own ArrayAdapter



我是Android Studio编程的初学者,我现在正在通过蓝牙制作某种信使。所以我有自己的 ArrayAdapter 类,它扩展了 ArrayAdapter 类,它用于传出和传入消息。我希望传入消息位于左侧,传出消息位于右侧,因此我为此适配器制作了两种布局。我知道,在stackoverflow上有很多解决方案可以使ArrayAdapter每行具有很少的不同布局,但是它们中的每一个都不起作用 - 更改布局会导致每行的视图更改。所以我的解决方案是制作另一个布尔值的 ArrayList,并在 getView(( 中检查我在这个列表中的内容 - 真或假 - 并在 ArrayAdapter 中的该行上使用正确的布局(我正在通过 getView(( 的位置字段检查它(。当我向第二台设备发送大量消息并尝试响应第一台设备时,会出现 NullPointerException 符合(TextView)row.findViewById(R.id.singleIncomingMessage);

(TextView)row.findViewById(R.id.singleOutgoingMessage);

这种例外似乎出现在随机情况下,但当然一定有一些模式。这是整个代码。怎么了?如果有一些拼写错误,我很抱歉我的语言;)

public class MyArrayAdapter extends ArrayAdapter<String> {
public MyArrayAdapter(Context context, ArrayList<String> list) {
super(context, 0, list);
this.list =list;
this.context=context;
}
ArrayList<String> list;
Context context;
@Override
public int getCount() {
return list.size();
}
@Override
public String getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
if(Messenger.inOut){
return 1;
}
else{
return 0;
}
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int type=getItemViewType(position);
View row=convertView;
if(row==null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(Messenger.inOutList.get(position)==0){
row=inflater.inflate(R.layout.outgoing_message_layout, parent, false);
}
if(Messenger.inOutList.get(position)==1){
row=inflater.inflate(R.layout.incoming_message_layout, parent, false);
}
}
String message=getItem(position);
TextView label;
if(Messenger.inOutList.get(position)==0){
label=(TextView)row.findViewById(R.id.singleOutgoingMessage);
label.setText(message);
}
if(Messenger.inOutList.get(position)==1){
label=(TextView)row.findViewById(R.id.singleIncomingMessage);
label.setText(message);
}
return row;
}
}

我认为问题来自row为非空的情况。它可能以前被夸大为传出邮件布局,现在您正在回收它并尝试将其视为传入邮件布局,因此它找不到TextView

很难确定这是问题所在,因为我真的不知道Messenger.*调用在您的代码中的行为方式。由于您已经获得了getViewtype因此您应该使用它而不是Messenger.inOutList.get(position)==X来确定如果保持这种方式要使用哪种视图逻辑。这个问题在如何始终如一地做到这一点方面有一些很好的答案。

另请记住,要使其正常工作getItemViewType必须始终为给定位置返回相同的类型,否则您必须检测更改并在getView中膨胀新布局。如果Messenger.inOut是常量,则没有理由使用此格式(多布局格式(。如果它不是一个常量并且它被更改了,那么你需要在getView中检测到这一点

好的,非常感谢,我终于做到了。我使用了两个列表(布尔值和消息(,在我阅读了 ArrayAdapter 之后,我决定使用这两个字段进行类并列出其对象。这个错误可能是因为第二个布尔值列表。如果有人有类似的问题,这是我的最终代码。

public class MyArrayAdapter extends ArrayAdapter<MessageWithType> {
public MyArrayAdapter(Context context, ArrayList<MessageWithType> list) {
super(context, 0, list);
this.list =list;
this.context=context;
}
public static final int TYPE_OUT = 0;
public static final int TYPE_IN = 1;
ArrayList<MessageWithType> list;
Context context;
@Override
public int getCount() {
return list.size();
}
@Override
public MessageWithType getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
if(list.get(position).inOut){
return 1;
}
else{
return 0;
}
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
MessageWithType item=getItem(position);
int type=getItemViewType(position);
View row=convertView;
ViewHolder viewHolder=null;
if(row==null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(type==TYPE_OUT){
row=inflater.inflate(R.layout.outgoing_message_layout, parent, false);
}
if(type==TYPE_IN){
row=inflater.inflate(R.layout.incoming_message_layout, parent, false);
}
TextView label=(TextView)row.findViewById(R.id.singleMessage);
viewHolder=new ViewHolder(label);
row.setTag(viewHolder);
}
else{
viewHolder=(ViewHolder)row.getTag();
}
viewHolder.textView.setText(item.message);
return row;
}
public class ViewHolder{
TextView textView;
public ViewHolder(TextView textView){
this.textView=textView;
}
}

}

最新更新