我是Android Studio编程的初学者,现在通过蓝牙制作某种Messenger。所以我有自己的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;
}
}
答案 0 :(得分:0)
我认为问题出在row
非空的情况下。它可能以前被夸大为外发邮件布局,现在您正在回收它并尝试将其视为外来邮件布局,因此找不到TextView
。
尽管我真的不知道Messenger.*
调用在代码中的行为,但是很难确定这是问题所在。由于您已经在type
中获得了getView
,因此,如果保持这种方式,则应该使用该视图而不是Messenger.inOutList.get(position)==X
来确定使用哪种视图逻辑。 This question对于如何一致地执行此操作有一些很好的答案。
还请记住,要执行此操作,getItemViewType
必须始终为给定位置返回相同的类型,否则必须检测到更改并在getView
中填充新的布局。如果Messenger.inOut
为常数,则没有理由使用此格式(多布局格式)。如果它不是一个常数并且被更改,那么您需要在getView
答案 1 :(得分:0)
好的,非常感谢,我终于做到了。我使用了两个列表(布尔值和消息),在我了解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;
}
}
}