0

I'm trying to emulate a simple chat view using two layouts, one for sent and one for received message. When i try to scroll, a NullPointerException is thrown. Not sure why this happens. Can someone find the problem.

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 and received_message layouts

    <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

Code that calls the adapter

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

After change

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
  • stackoverflow.com/questions/18868194/…. i guess you are looking for something similar Commented Dec 23, 2013 at 8:50
  • how do you differentiate b/w send and receive messages? Commented Dec 23, 2013 at 8:59
  • Any string thats not null has data. So either sent or received will have data. Commented Dec 23, 2013 at 9:01

3 Answers 3

1

You forgot to override the following methods

    @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;
    }
Sign up to request clarification or add additional context in comments.

6 Comments

don't needed in ArrayAdapter, its must be override in BaseAdapter
Ok..@Shayanpourvatan then on what basis the getView() method get called?
i'm not sure but i think so with super constructor.super(context, sentResource, rcvdResource, messages);
@RBM no need to override getCount since op has super(context, sentResource, rcvdResource, messages);
@Raghunandan stackoverflow.com/questions/18868194/… Here, I haven't seen any super call like super(context, sentResource, rcvdResource, messages);
|
0

The null pointer exception may be caused at these places-

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

It is because, first time you are inflating your row layouts based on messages.sent.Suppose in first case it is a sent message so you inflate row layout for sent message, initialize the sent text view of the MessagesHolder.When you start scrolling, the views are not null so they are not redrawn, so at this time a recieved message comes in the position previously occupied by a sent message, it tries to set text on textView holder.recived , which has not been initialized previously and results in a null pointer exception.

Solution- Use just one row layout for both cases and one text view member in MessagesHolder class.

3 Comments

No. same exception comes up.
use single row layout xml for both cases having a plain text view.Set the background(or any other parameters for differentiating sent and received message) of the textview programatically(inside getview based on the condition for sent or received message).Hope you got it.
0

Temproary Solution :

The problem seems to be in the holder and it's use. It works now if i dont use the holder class for performance boost and do the naive implementation. Although i'm not sure how to use the holder properly, if one needs performance boost.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.