簡體   English   中英

Android-使用自定義適配器在ListView中滾動時發生NullPointerException

[英]Android - NullPointerException while scrolling in listview with custom adapter

我正在嘗試使用兩種布局模擬一個簡單的聊天視圖,一種用於發送消息,一種用於接收消息。 當我嘗試滾動時,拋出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的

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 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);
}

變更后

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;


}

}

您忘記了覆蓋以下方法

    @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;
    }

空指針異常可能是在這些地方引起的-

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

這是因為,第一次您是基於messages.sent來擴大行布局的,假設在第一種情況下它是已發送的消息,因此您要為已發送的消息增加行的布局,請初始化MessagesHolder的已發送文本視圖。開始滾動時,視圖不是null,因此它們不會被重繪,因此,此時接收到的消息位於發送消息之前占據的位置,它嘗試在textViewholder.recived上設置文本,該文本先前尚未初始化,並導致空指針異常。

解決方案-在MessagesHolder類中,僅對兩種情況使用一個行布局,對一個文本視圖成員使用。

臨時解決方案:

問題似乎出在持有人及其使用中。 現在,如果我不使用holder類來提高性能並進行簡單的實現,它現在就可以工作。 盡管我不確定如何正確使用支架,但是如果需要提高性能的話。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM