Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android

EditFriendsFragment not working as expected in the Ribbit app

Hi Ben,

I am using EditFriendsFragment instead of just Activity and everything was working fine with your code. But then I tried to optimize the addFriendsCheckmark() method which was O(n^2) and replaced it with an O(n) method using a HashMap. The problem: when I add a checkmark to my friends it does not reflect on resuming the EditFriendsFragment. But strangely when I add checkmark to myself(including/excluding friends), the checkmark reflects correctly wherever applied. I guess there is some problem with the objectIds but I am not sure what it is.

Thanks, Ankit

Code from onResume() for EditFriendsFragment:

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

            // Choose multiple friends
            getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

            mCurrentUser = ParseUser.getCurrentUser();
            mFriendRelation = mCurrentUser.getRelation(ParseConstants.KEY_FRIENDS_RELATION);

            // Activate progress indicator
            getActivity().setProgressBarIndeterminateVisibility(true);

            ParseQuery<ParseUser> query = ParseUser.getQuery();
            query.addAscendingOrder(ParseConstants.KEY_USERNAME);
            query.setLimit(ParseConstants.MAX_USER_LIMIT);
            query.findInBackground(new FindCallback<ParseUser>() {

                @Override
                public void done(List<ParseUser> users, ParseException e) {
                    // Deactivate progress indicator
                    getActivity().setProgressBarIndeterminateVisibility(false);

                    final Map<ParseUser, Boolean> usersMap = new HashMap<ParseUser, Boolean>();
                    if (e == null) {
                        mUsers = users;

                        // Put all users in HashMap
                        for (ParseUser user : mUsers) {
                            usersMap.put(user, false);
                        }

                        // Log details
                        for (Map.Entry<ParseUser, Boolean> user : usersMap.entrySet()) {
                            Log.i(TAG, "User: " + user.getKey().getUsername() + " " + "Friend: " + user.getValue());
                        }

                        final String[] usernames = new String[mUsers.size()];
                        int i = 0;
                        for (ParseUser user : mUsers) {
                            usernames[i] = user.getUsername();
                            i++;
                        }
                        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), 
                                android.R.layout.simple_list_item_checked, usernames);
                        setListAdapter(adapter);

                        //addFriendsCheckmark();

                        // Set a boolean for matching friends
                        mFriendRelation.getQuery().findInBackground(new FindCallback<ParseUser>() {
                            @Override
                            public void done(List<ParseUser> friends, ParseException e) {
                                if (e == null) {

                                    Log.i(TAG, "Friends List size: " + friends.size());

                                    for (ParseUser friend : friends) {
                                        Log.i(TAG, "Friend: " + friend.getUsername());
                                    }

                                    for (ParseUser friend : mUsers) {
                                        Log.i(TAG, "mUser Friend: " + friend.getUsername());
                                    }

                                    int i = 0;
                                    for (ParseUser friend : friends) {
                                        ParseUser user = mUsers.get(i);
                                        if ((friend.getObjectId()).equals(user.getObjectId())) {
                                            Log.i(TAG, "Switch boolean for " + friend.getUsername() + " Id: " + friend.getObjectId());
                                            usersMap.put(friend, true);
                                        }
                                        i++;
                                    }

                                    // Log details
                                    for (Map.Entry<ParseUser, Boolean> user : usersMap.entrySet()) {
                                        Log.i(TAG, "[In Background] User: " + user.getKey().getUsername() + " " + "Friend: " + user.getValue());
                                    }

                                    // Add checkmark to friends
                                    for (Map.Entry<ParseUser, Boolean> user : usersMap.entrySet()) {
                                        if (user.getValue()) {
                                            String username = user.getKey().getUsername();
                                            getListView().setItemChecked(Arrays.asList(usernames).indexOf(username), true);
                                        }
                                    }
                                }
                                else {
                                    Log.e(TAG, e.getMessage());
                                }
                            }
                        });
                    }
                    else {
                        Log.e(TAG, e.getMessage());
                        // Display error message
                        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                        builder.setMessage(e.getMessage());
                        builder.setTitle(R.string.error_title);
                        builder.setPositiveButton(android.R.string.ok, null);
                        AlertDialog dialog = builder.create();
                        dialog.show();
                    }
                }
            });
        }

1 Answer

Ben Jakuben
STAFF
Ben Jakuben
Treehouse Teacher

I think this is your trouble spot:

int i = 0;
for (ParseUser friend : friends) {
    ParseUser user = mUsers.get(i);
    if ((friend.getObjectId()).equals(user.getObjectId())) {
        Log.i(TAG, "Switch boolean for " + friend.getUsername() + " Id: " + friend.getObjectId());
        usersMap.put(friend, true);
    }
    i++;
}

I added this statement before the if block to see what was going on:

Log.i(TAG, "friend ID: " + friend.getObjectId() + " || user ID: " + user.getObjectId());

That made me realize you're looping through friends and mUsers at the same time. So you still aren't checking each friend against each user or vice versa.

I'm glad you're trying to optimize this, though. I wasn't thrilled with this approach, but it seemed the simplest method to explain without getting into Big O Notation or other things I thought were beyond the scope of this course. I had a different solution somewhere...I'll see if I can find it. Let us know in here if you modify your approach. :)

Thanks Ben! I did not realize that earlier; I re-thought the whole process..finally, I fixed it :)

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

            // Choose multiple friends
            getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

            mCurrentUser = ParseUser.getCurrentUser();
            mFriendRelation = mCurrentUser.getRelation(ParseConstants.KEY_FRIENDS_RELATION);

            // Activate progress indicator
            getActivity().setProgressBarIndeterminateVisibility(true);

            ParseQuery<ParseUser> query = ParseUser.getQuery();
            query.addAscendingOrder(ParseConstants.KEY_USERNAME);
            query.setLimit(ParseConstants.MAX_USER_LIMIT);
            query.findInBackground(new FindCallback<ParseUser>() {

                @Override
                public void done(List<ParseUser> users, ParseException e) {
                    // Deactivate progress indicator
                    getActivity().setProgressBarIndeterminateVisibility(false);

                    final Map<String, ParseUser> usersMap = new HashMap<String, ParseUser>();

                    if (e == null) {
                        mUsers = users;

                        // Put all users in HashMap
                        for (ParseUser user : mUsers) {
                            usersMap.put(user.getObjectId(), user);
                        }

                        final String[] usernames = new String[mUsers.size()];
                        int i = 0;
                        for (ParseUser user : mUsers) {
                            usernames[i] = user.getUsername();
                            i++;
                        }
                        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), 
                                android.R.layout.simple_list_item_checked, usernames);
                        setListAdapter(adapter);

                        //addFriendsCheckmark();

                        // TODO Optimization O(n)
                        mFriendRelation.getQuery().findInBackground(new FindCallback<ParseUser>() {
                            @Override
                            public void done(List<ParseUser> friends, ParseException e) {
                                if (e == null) {

                                    // Add checkmark to friends
                                    for (ParseUser friend : friends) {
                                        ParseUser user = usersMap.get(friend.getObjectId());
                                        if (user != null) {
                                            String username = friend.getUsername();
                                            getListView().setItemChecked(Arrays.asList(usernames).indexOf(username), true);
                                        }
                                    }
                                }
                                else {
                                    Log.e(TAG, e.getMessage());
                                }
                            }
                        });
                    }
                    else {
                        Log.e(TAG, e.getMessage());
                        // Display error message
                        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                        builder.setMessage(e.getMessage());
                        builder.setTitle(R.string.error_title);
                        builder.setPositiveButton(android.R.string.ok, null);
                        AlertDialog dialog = builder.create();
                        dialog.show();
                    }
                }
            });
        }