0

我試圖模擬一個簡單的聊天視圖,使用兩個佈局,一個用於發送,另一個用於接收消息。當我嘗試滾動時,引發NullPointerException。不知道爲什麼會發生。有人可以找到問題。android-NullPointerException在使用自定義適配器在列表視圖中滾動時

public class DisplayMessageAdapter extends ArrayAdapter<Message> { 

Context context; 
int sentResource, rcvdResource; 
ArrayList<Message> messages = null; 

public DisplayMessageAdapter(Context context, int sentResource, int rcvdResource, ArrayList<Message> messages) { 
    super(context, sentResource, rcvdResource, messages); 
    this.context = context; 
    this.sentResource = sentResource; 
    this.rcvdResource = rcvdResource; 
    this.messages = messages; 
} 

@SuppressLint("NewApi") 
@Override 
public View getView(int position, View convertView, ViewGroup parent) { 

    View row = convertView; 
    MessagesHolder holder = null; 

    Message message = messages.get(position); 


    if(message.sent != null) 
    { 

     if(row == null) 
     { 
      LayoutInflater inflater = (LayoutInflater) context 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      row = inflater.inflate(sentResource, parent, false); 

      holder = new MessagesHolder(); 
      holder.sent = (TextView) row.findViewById(R.id.sent_message); 
      row.setTag(holder); 
     } 

     else 
     { 
      //Log.i("holder-not-null","holder-not-null"); 
      holder = (MessagesHolder) row.getTag(); 
     } 

     holder.sent.setText(message.sent); 
    } 
    else 
    { 
     if(row == null) 
     { 
      LayoutInflater inflater = (LayoutInflater) context 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      row = inflater.inflate(rcvdResource, parent, false); 

      holder = new MessagesHolder(); 
      holder.received = (TextView) row.findViewById(R.id.received_message); 
      row.setTag(holder); 
     } 

     else 
     { 
      //Log.i("holder-not-null","holder-not-null"); 
      holder = (MessagesHolder) row.getTag(); 
     } 

     holder.received.setText(message.received); 

    } 

    return row; 
} 

static class MessagesHolder 
{ 
    TextView sent; 
    TextView received; 

} } 

sent_message和received_message佈局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
     <TextView 
     android:id="@+id/sent_message" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_marginLeft="20dp" 
     android:textColor="#000000" 
     android:background="@drawable/sent" 
     android:layout_marginTop="4dp" 
     android:layout_marginBottom="4dp" 
     android:textSize="15sp" 
     /> 

</RelativeLayout> 

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 

     <TextView 
      android:layout_alignParentRight="true" 
      android:id="@+id/received_message" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:background="@drawable/rcvd" 
      android:layout_marginRight="20dp" 
      android:textColor="#000000" 
      android:layout_marginTop="4dp" 
      android:layout_marginBottom="4dp" 
      android:textSize="15sp" 
      /> 

</RelativeLayout> 

logcat中調用該適配器

public void populateView(ArrayList<Message> allMessages) 
{ 
    DisplayMessageAdapter adapter = new DisplayMessageAdapter(getApplicationContext() , R.layout.sent_message_layout, R.layout.received_message_layout, allMessages); 
    listview = (ListView) findViewById(R.id.messageview); 
    listview.setAdapter(adapter); 
    listview.setSelection(listview.getAdapter().getCount()-1); 
} 

變化

12-23 13:46:04.996: E/AndroidRuntime(8131): FATAL EXCEPTION: main 
12-23 13:46:04.996: E/AndroidRuntime(8131): java.lang.NullPointerException 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at com.example.swipetext.DisplayMessageAdapter.getView(DisplayMessageAdapter.java:58) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.widget.AbsListView.obtainView(AbsListView.java:2608) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.widget.ListView.makeAndAddView(ListView.java:1852) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.widget.ListView.fillUp(ListView.java:718) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.widget.ListView.fillGap(ListView.java:655) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.widget.AbsListView.trackMotionScroll(AbsListView.java:6592) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3706) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.widget.AbsListView.onTouchEvent(AbsListView.java:4556) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.View.dispatchTouchEvent(View.java:7817) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2435) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2159) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2441) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2174) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2441) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2174) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2441) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2174) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2441) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2174) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2326) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1612) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.app.Activity.dispatchTouchEvent(Activity.java:2494) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2274) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.View.dispatchPointerEvent(View.java:8025) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4659) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4547) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4148) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4198) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4167) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4252) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4175) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4309) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4148) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4198) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4167) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4175) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4148) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6293) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6231) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6202) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6373) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:188) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:177) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:6346) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:6392) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:791) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.Choreographer.doCallbacks(Choreographer.java:591) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.Choreographer.doFrame(Choreographer.java:559) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:777) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.os.Handler.handleCallback(Handler.java:730) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.os.Handler.dispatchMessage(Handler.java:92) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.os.Looper.loop(Looper.java:137) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at android.app.ActivityThread.main(ActivityThread.java:5419) 
12-23 13:46:04.996: E/AndroidRuntime(8131):  at java.lang.reflect.M 

代碼

public class DisplayMessageAdapter extends ArrayAdapter<Message> { 

Context context; 
int sentResource, rcvdResource; 
ArrayList<Message> messages = null; 

public DisplayMessageAdapter(Context context, int sentResource, int rcvdResource, ArrayList<Message> messages) { 
    super(context, sentResource, rcvdResource, messages); 
    this.context = context; 
    this.sentResource = sentResource; 
    this.rcvdResource = rcvdResource; 
    this.messages = messages; 
} 

@SuppressLint("NewApi") 
@Override 
public View getView(int position, View convertView, ViewGroup parent) { 

    View row = convertView; 
    MessagesHolder holder = null; 

    Message message = messages.get(position); 


    if(message.sent != null) 
    { 

     if(row == null) 
     { 
      LayoutInflater inflater = (LayoutInflater) context 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      row = inflater.inflate(sentResource, parent, false); 

      holder = new MessagesHolder(); 
      holder.data = (TextView) row.findViewById(R.id.sent_message); 
      row.setTag(holder); 
     } 

     else 
     { 
      //Log.i("holder-not-null","holder-not-null"); 
      holder = (MessagesHolder) row.getTag(); 
     } 

     holder.data.setText(message.sent); 
    } 
    else 
    { 
     if(row == null) 
     { 
      LayoutInflater inflater = (LayoutInflater) context 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      row = inflater.inflate(rcvdResource, parent, false); 

      holder = new MessagesHolder(); 
      holder.data = (TextView) row.findViewById(R.id.received_message); 
      row.setTag(holder); 
     } 

     else 
     { 
      //Log.i("holder-not-null","holder-not-null"); 
      holder = (MessagesHolder) row.getTag(); 
     } 

     holder.data.setText(message.received); 

    } 

    return row; 
} 

static class MessagesHolder 
{ 
    TextView data; 


} 

}

+3

發表您的logcat」 – Dhananjay

+0

http://stackoverflow.com/questions/18868194/android-xml-layout-for-a-listview-with-different-items。我想你正在尋找類似的東西 – Raghunandan

+0

你如何區分黑白的發送和接收消息? – Raghunandan

回答

1

你忘了覆蓋以下方法

@Override 
    public int getCount() { 
     // TODO Auto-generated method stub 
     return messages.size(); 
    } 

    @Override 
    public Object getItem(int position) { 
     return position; 
    } 

    @Override 
    public long getItemId(int position) { 
     // TODO Auto-generated method stub 
     return position; 
    } 
+0

在'ArrayAdapter'中不需要,它必須在'BaseAdapter'中覆蓋。 –

+0

好的。@ Shayanpourvatan然後調用getView()方法的基礎是什麼? –

+0

我不確定,但我認爲超級構造函數.'super(context,sentResource,rcvdResource,messages);' –

0

空指針異常可能在這些地方 -

holder.sent.setText(message.sent); 
holder.received.setText(message.received); 

引起這是因爲,第一次正在根據消息擴大你的行佈局。在第一種情況下假設它是一個已發送的消息,所以你膨脹了發送消息的行佈局,initializ e MessageHolder的發送文本視圖。當您開始滾動時,視圖不爲空,因此它們不會重繪,因此此時接收到的消息進入先前被髮送消息佔據的位置,它會嘗試在textView上設置文本holder.recived,它以前沒有被初始化,並導致空指針異常。

解決方案- 對於兩種情況和MessagesHolder類中的一個文本視圖成員只使用一個行佈局。

+0

你的意思是? http://stackoverflow.com/questions/20737222/android-custom-listview-changes-while-shrolling – brainfreak

+0

編號相同的例外出現。 – brainfreak

+0

對具有純文本視圖的兩種情況使用單行佈局xml。以編程方式設置背景(或用於區分發送和接收消息的任何其他參數)(根據發送或接收消息的條件在getview中)。希望你得到它了。 – nikvs

0

Temproary解決方案:

的問題似乎是在支架和它的使用。它現在的作品,如果我不使用持有人類的性能提升和做天真的實施。雖然我不確定如何正確使用持有者,但如果需要提升性能的話。

0

覆蓋getCount()方法並返回List的長度。

public class DisplayMessageAdapter extends ArrayAdapter<Message> { 

@Override 
public int getCount() { 
    return Message.size(); 

} 
} 
相關問題