Search code examples
javaandroidlistviewchatlistview-adapter

How to show chats by collecting messages in the custom list view adapter itself?


So, What I want to do is display chats in my activity using a custom list view adapter.

I have a HTTPTask Activity handling the server side interaction and responding with a JSONObject. So, every server side interaction is working fine.

What I want to do is keep updating the messages in the chat by keep checking with the API at a set interval to populate messages in the chat if there are any.

My question is, should this population process done in the adapter or the activity and how?

And, how does viewHolder help in the adapter?

This is my Activity

public class ChatActivity extends Activity {

TextView toUsername;
EditText replyText;
JSONObject resultObject;
StringBuilder reply,from_user_id,c_id;
MessageListViewAdapter myAdapter;
ListView listView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_chat);

    toUsername = (TextView) findViewById(R.id.toUsername);
    replyText = (EditText) findViewById(R.id.replyText);
    reply = new StringBuilder("");
    listView = (ListView) findViewById(R.id.messages);
}

@Override
public void onResume(){
    super.onResume();

    Bundle bundle = getIntent().getExtras();
    if(bundle != null){
        toUsername.setText("" + bundle.get("ToUsername").toString());
        c_id = new StringBuilder(bundle.get("c_id").toString());
        from_user_id = new StringBuilder(bundle.get("FromUserId").toString());
    }

    myAdapter = new MessageListViewAdapter(getBaseContext(),c_id.toString(),from_user_id.toString());
    listView.setAdapter(myAdapter);
}

public void sendTextMsg(View view){
    reply.delete(0,reply.length());
    reply.append(replyText.getText().toString());
    if(!reply.toString().equals("")){
        Log.d("Values: ","c_id: " + c_id.toString() + " FromUserId: " + from_user_id.toString() + "ReplyText: " + reply.toString());

        try{
            resultObject = new HttpTask(getBaseContext()).doInBackground("replyInChat",c_id.toString(),replyText.getText().toString(),from_user_id.toString());
            if(resultObject.get("status").toString().equals("true")) {
                Toast.makeText(getBaseContext(), "Sent.", Toast.LENGTH_SHORT).show();
                replyText.setText("");
            }
            else {
                Toast.makeText(getBaseContext(), "Try Again.", Toast.LENGTH_SHORT).show();
            }
        }
        catch(JSONException e){ }

    }
}
}

My Adapter doesn't seem to work.

public class MessageListViewAdapter extends BaseAdapter implements ListAdapter{

private ArrayList<String> list = new ArrayList<String>();
private Context context;
private StringBuilder conversation_id, user_id;
private static int cr_id;
private JSONArray messages;
private JSONObject resultObject;
private ViewHolder viewHolder;
private View rowView;

public MessageListViewAdapter(Context context, String conversation_id, String user_id) {
    this.context = context;
    this.conversation_id = new StringBuilder(conversation_id.toString());
    this.user_id = new StringBuilder(user_id.toString());
    cr_id=0;
}

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

@Override
public Object getItem(int pos) {
    return list.get(pos);
}

@Override
public long getItemId(int pos) {
    //return list.get(pos).getId();
    //just return 0 if your list items do not have an Id variable.
    return 0;
}

@Override
public boolean isEnabled(int position){
    return false;
}

static class ViewHolder{
    public TextView ItemText;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    rowView = convertView;

    if (rowView == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        rowView = inflater.inflate(R.layout.message_list_layout, null);
        //configure view holder
        viewHolder = new ViewHolder();
        viewHolder.ItemText = (TextView) rowView.findViewById(R.id.list_item_text);
        rowView.setTag(viewHolder);
    }
    else {
        //fill data
        viewHolder = (ViewHolder) rowView.getTag();
    }

    try{
        Log.d("cr_id: ",String.valueOf(cr_id).toString());
        //This is where the population should've taken place but didn't.
        resultObject = new HttpTask(context).doInBackground("sendMessages",conversation_id.toString(),String.valueOf(cr_id));
        if(resultObject.get("status").toString().equals("true")) {
            messages = resultObject.getJSONArray("messages");
            Log.d("Messages: ",messages.toString());
            for(int i=0;i<=messages.length();i++){
                list.add(messages.getJSONObject(i).get("reply_text").toString());
            }
        }
    }
    catch(JSONException e){ }

    //Handle TextView and display string from your list
    //final TextView listItemText = (TextView)rowView.findViewById(R.id.list_item_text);
    //listItemText.setText(list.get(position));
    viewHolder.ItemText.setText(list.get(position));

    return rowView;
}
}

Solution

  • So, Finally I got it working with some experimentation. Many thanks to Manikanta and Andy Joyce for their valuable answers. If it weren't for them i wouldn't have gone any further from where I was stuck.

    This is what I changed in my custom adapter.

    public void add(ArrayList<String> list){
        this.list.clear();
        this.list.addAll(list);
        Log.d("List: ",this.list.toString());
        this.notifyDataSetChanged();
    }
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        rowView = convertView;
    
        if (rowView == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            rowView = inflater.inflate(R.layout.message_list_layout, null);
            //configure view holder
            viewHolder = new ViewHolder();
            viewHolder.ItemText = (TextView) rowView.findViewById(R.id.list_item_text);
            rowView.setTag(viewHolder);
        }
    
        else {
            //fill data
            viewHolder = (ViewHolder) rowView.getTag();
        }
    
        viewHolder.ItemText.setText(list.get(position));
    
        return rowView;
    }
    

    This is what I added to my activity

        @Override
    public void onResume(){
        super.onResume();
    
        Bundle bundle = getIntent().getExtras();
        if(bundle != null){
            toUsername.setText("" + bundle.get("ToUsername").toString());
            c_id = new StringBuilder(bundle.get("c_id").toString());
            from_user_id = new StringBuilder(bundle.get("FromUserId").toString());
            //list.add(c_id.toString());
            //list.add(from_user_id.toString());
        }
    
        myAdapter = new MessageListViewAdapter(getBaseContext(),c_id.toString(),from_user_id.toString());
        listView.setAdapter(myAdapter);
    
        callAsynchronousTask();
        //myAdapter.add(list);
    }
    @Override
    public void onPause(){
        super.onPause();
        timer.cancel();
    }
    public void callAsynchronousTask() {
        final Handler handler = new Handler();
        timer = new Timer();
        TimerTask doAsynchronousTask = new TimerTask() {
            @Override
            public void run() {
                handler.post(new Runnable() {
                    public void run() {
                        //list.clear();
                        try{
                            resultChatObject = new HttpTask(getBaseContext()).doInBackground("sendMessages",c_id.toString(),String.valueOf(cr_id));
                            if(resultChatObject.get("status").toString().equals("true")) {
                                //list.clear();
                                messages = resultChatObject.getJSONArray("messages");
                                Log.d("Messages: ",messages.toString());
                                for (int i = 0; i <= messages.length(); i++) {
                                    list.add(messages.getJSONObject(i).get("reply_text").toString());
                                    if (cr_id < Integer.parseInt(messages.getJSONObject(i).get("cr_id").toString()))
                                        cr_id = Integer.parseInt(messages.getJSONObject(i).get("cr_id").toString());
                                }
                            }
                        }
                        catch (JSONException e) { }
    
                        myAdapter.add(list);
                    }
                });
            }
        };
        timer.schedule(doAsynchronousTask, 0, 10000); //execute in every 10000 ms
    }
    

    Cheers everyone!!!