Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Android Build a Self-Destructing Message Android App Self-Destruction Maintaining Scroll Position in a ListView

Two InboxFragment.java issues

Hi all,

So far, my app works as it should which is a miracle - I usually get something wrong!

However, there's a couple of little points that aren't quite up to speed in the Inbox. Maybe you can point me in the right direction.

Firstly, the senderName isn't displayed in the list. I just have a blank row. I've made sure that the TextView is set to match_parent so there's definitely sufficient width there to display the names. I've also compared my code to the video - that appears correct too. I'm assuming that the for loop that iterates through usernames[i] collects the senderName from the ParseConstants class member, KEY_SENDER_NAME?

Secondly, whether my message is a video or a photo, I only have the photo icon - I can't find where this is determined. Can you point me to that part of the code so I can try and fix it (or add it!!).

Thanks,

Steve.

Ben Jakuben - if you could have a look at this, it'd really help me out!

Thanks!

Steve. :-)

Ben Jakuben
Ben Jakuben
Treehouse Teacher

Cool - paste in your code and I'll take a look! Paste in everything from InboxFragment. I'll help reformat it if you have any trouble.

3 Answers

Thanks, Ben Jakuben - here's that file!

package uk.co.bigdogconsultants.ribbit;

import java.util.ArrayList;
import java.util.List;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;

import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.ParseFile;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseUser;

public class InboxFragment extends ListFragment {

    protected List<ParseObject> mMessages;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_inbox, container, false);

        return rootView;
    }

    @Override
    public void onResume() {
        super.onResume();
        getActivity().setProgressBarIndeterminate(true);
        ParseQuery<ParseObject> query = new ParseQuery<ParseObject>(ParseConstants.CLASS_MESSAGES);
        query.whereEqualTo(ParseConstants.KEY_RECIPIENT_IDS, ParseUser.getCurrentUser().getObjectId());
        query.addDescendingOrder(ParseConstants.KEY_CREATED_AT);
        query.findInBackground(new FindCallback<ParseObject>() {

            @Override
            public void done(List<ParseObject> messages, ParseException e) {
                getActivity().setProgressBarIndeterminateVisibility(false);

                if(e == null) {
                    // we found messages
                    mMessages = messages;
                    String[] usernames = new String[mMessages.size()];
                    int i = 0;
                    for(ParseObject message : mMessages) {
                        usernames[i] = message.getString(ParseConstants.KEY_SENDER_NAME);
                        i++;
                    }
                    if(getListView().getAdapter() == null) {
                        MessageAdapter adapter = new MessageAdapter(
                                getListView().getContext(), 
                                mMessages);
                        setListAdapter(adapter);
                    }
                    else {
                        // refresh the adapter
                        ((MessageAdapter)getListView().getAdapter()).refill(mMessages);
                    }
                }

            }
        });
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {

        super.onListItemClick(l, v, position, id);

        ParseObject message = mMessages.get(position);
        String messageType = message.getString(ParseConstants.KEY_FILE_TYPE);
        ParseFile file = message.getParseFile(ParseConstants.KEY_FILE);
        Uri fileUri = Uri.parse(file.getUrl());

        if(messageType.equals(ParseConstants.TYPE_IMAGE)) {
            // view image
            Intent intent = new Intent(getActivity(), ViewImageActivity.class);
            intent.setData(fileUri);
            startActivity(intent);

        }   
        else {
            // view video
            Intent intent = new Intent(Intent.ACTION_VIEW, fileUri);
            intent.setDataAndType(fileUri, "video/*");
            startActivity(intent);
        }
        // delete
        List<String> ids = message.getList(ParseConstants.KEY_RECIPIENT_IDS);

        if(ids.size() == 1) {
            //delete all
            message.deleteInBackground();
        }
        else {
            // delete user & save
            ids.remove(ParseUser.getCurrentUser().getObjectId());
            ArrayList<String> idsToRemove = new ArrayList<String>();
            idsToRemove.add(ParseUser.getCurrentUser().getObjectId());
            message.removeAll(ParseConstants.KEY_RECIPIENT_IDS, idsToRemove);
            message.saveInBackground();

        }


    }

}

Cheers,

Steve.

Ben Jakuben
Ben Jakuben
Treehouse Teacher

Ah, I should have asked to see your Adapter code instead. My bad! Can you paste in your MessageAdapter class?

Hi Ben,

I'm trying this on the phone... I hope it goes ok!

package uk.co.bigdogconsultants.ribbit;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.parse.ParseObject;

public class MessageAdapter extends ArrayAdapter<ParseObject>{

    protected Context mContext;
    protected List<ParseObject> mMessages;

    public MessageAdapter(Context context, List<ParseObject> messages) {
        super(context, R.layout.message_item, messages);

        mContext = context;
        mMessages = messages;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if(convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.message_item,  null);
            holder = new ViewHolder();
            holder.iconImageView = (ImageView)convertView.findViewById(R.id.messageIcon);
            holder.nameLabel = (TextView)convertView.findViewById(R.id.senderLabel);
            convertView.setTag(holder);
        }
        else {
            holder = (ViewHolder) convertView.getTag();
        }
        ParseObject message = mMessages.get(position);

        return convertView;
    }

    private static class ViewHolder{
        ImageView iconImageView;
        TextView nameLabel;
    }

    public void refill(List<ParseObject> messages) {
        mMessages.clear();
        mMessages.addAll(messages);
        notifyDataSetChanged();
    }
}

It didn't. Sorry!

Ben Jakuben
Ben Jakuben
Treehouse Teacher

Good enough! I reformatted it. And this shows the error! Each item in a ListView is drawn one at a time by the getView() method. This method gets called for each item, and it either creates or reuses a layout (it reuses when it can to conserve memory and make the list scroll faster). This method is where you need to assign your sender name and the icon type. Check the videos again to see what's missing from this section, or let me know in here if you need specific help with the missing code. :)

How the hell did I miss that?!

Code inserted and, unsurprisingly, that now works!

Again, Ben Jakuben , thank you for your help!!

I've already working through the Design Implementation section and Ribbit's beginning to look cool!

Thanks again,

Steve.