I am currently working on an app which contains a friends list when logged in and user profiles. When the user clicks on a friend in the friends list, I would like them to be directed to a profile page for this friend. To do this, I have been trying to extract the specific object id from the user that is clicked on in the list view and then pass that onto the next activity where I use it to run a query for all the users other attributes (name, email, hometown, etc.). I have figured out how to pass along data through intents but I am having all sorts of trouble obtaining the user id from the list item clicked. My onItemCLick code is below.
```
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
ParseObject item = (ParseObject) l.getAdapter().getItem(position);
String objectID = item.getObjectId().toString();
Intent intent = new Intent(getActivity(), FriendsProfileActivity.class);
intent.putExtra("ID", objectID);
startActivity(intent);
```
I have also tried something of this sort to not avail.
```
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
ParseObject item = (ParseObject) l.getAdapter().getItem(position);
item.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
if(e == null) {
String objectID = item.getObjectId();
Log.e(TAG, objectID);
Intent intent = new Intent(getActivity(), FriendsProfileActivity.class);
intent.putExtra("ID", objectID);
startActivity(intent);
}
else {
Log.e(TAG, e.getMessage());
}
}
});
}
```
In both cases, the app crashes when I click on the user in the list view. How can I succesfully pull the object ID from the user clicked on and pass it along?
Edit: Here is the logcat error.
Process: com.richluick.ribbit, PID: 2194
java.lang.ClassCastException: java.lang.String cannot be cast to com.parse.ParseObject
at com.richluick.ribbit.FriendsFragment.onListItemClick(FriendsFragment.java:83)
at android.support.v4.app.ListFragment$2.onItemClick(ListFragment.java:58)
at android.widget.AdapterView.performItemClick(AdapterView.java:299)
at android.widget.AbsListView.performItemClick(AbsListView.java:1113)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:2904)
at android.widget.AbsListView$3.run(AbsListView.java:3638)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Edit: Here is the full code for the activity including the query and list adapter. package com.richluick.ribbit;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseRelation;
import com.parse.ParseUser;
import com.parse.SaveCallback;
import java.util.List;
public class FriendsFragment extends android.support.v4.app.ListFragment {
public static final String TAG = FriendsFragment.class.getSimpleName();
protected List<ParseUser> mFriends;
protected ParseRelation<ParseUser> mFriendsRelation;
protected ParseUser mCurrentUser;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_friends, container, false);
return rootView;
}
@Override
public void onResume() {
super.onResume();
mCurrentUser = ParseUser.getCurrentUser();
mFriendsRelation = mCurrentUser.getRelation(ParseConstants.KEY_FRIENDS_RELATION);
getActivity().setProgressBarIndeterminateVisibility(true);
ParseQuery<ParseUser> query = mFriendsRelation.getQuery();
query.addAscendingOrder(ParseConstants.KEY_USERNAME);
query.findInBackground(new FindCallback<ParseUser>() {
@Override
public void done(List<ParseUser> friends, ParseException e) {
getActivity().setProgressBarIndeterminateVisibility(false);
if (e == null) {
mFriends = friends;
String[] usernames = new String[mFriends.size()];
int i = 0;
for (ParseUser user : mFriends) {
usernames[i] = user.getUsername();
i++;
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getListView().getContext(),
android.R.layout.simple_list_item_1, usernames);
setListAdapter(adapter);
}
else {
Log.e(TAG, e.getMessage());
AlertDialog.Builder builder = new AlertDialog.Builder(getListView().getContext());
builder.setTitle(R.string.error_title)
.setMessage(e.getMessage())
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
}
});
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
final ParseObject item = (ParseObject) l.getAdapter().getItem(position);
item.saveInBackground(new SaveCallback() {
@Override
public void done(ParseException e) {
if(e == null) {
String objectID = item.getObjectId();
Log.e(TAG, objectID);
Intent intent = new Intent(getActivity(), FriendsProfileActivity.class);
intent.putExtra("ID", objectID);
startActivity(intent);
}
else {
Log.e(TAG, e.getMessage());
}
}
});
}
}
Have a look at ParseQueryAdapter
Docs: https://parse.com/docs/android_guide#ui-queryadapter
Tutorial: https://parse.com/tutorials/parse-query-adapter
API: https://parse.com/docs/android/api/com/parse/ParseQueryAdapter.html.
Also I would recommend EventBus to pass the ParseObject to the next Activity https://github.com/greenrobot/EventBus.
Then you can do:
Adapter:
Intent intent = new Intent(getActivity(), FriendsProfileActivity.class);
EventBus.getDefault().postSticky(YourParseObject);
startActivity(intent);
Anywhere in FriendsProfileActivity:
ParseObject yourParseObject = EventBus.getDefault().getStickyEvent(ParseObject.class);
If you move on to using subclasses in parse.com, then any subclass can be sent via the EventBus this way.
Example code - untested but should be close to what you want
The ParseQueryAdapter:
The layout for R.layout.adapter_item_friend - can be customized but nothing fancy here
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:paddingTop="5dp">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="item" />
</RelativeLayout>
The Adapter:
public class ParseUserFriendsAdapter extends ParseQueryAdapter<ParseUser> {
private static final String TAG = ParseUserFriendsAdapter.class.getSimpleName();
public ParseUserFriendsAdapter(Context context) {
super(context, new ParseQueryAdapter.QueryFactory<ParseUser>() {
@Override
public ParseQuery<ParseUser> create() {
ParseUser currentUser = ParseUser.getCurrentUser();
ParseRelation<ParseUser> friendsRelation = currentUser.getRelation(ParseConstants.KEY_FRIENDS_RELATION);
ParseQuery<ParseUser> query = friendsRelation.getQuery();
query.addAscendingOrder(ParseConstants.KEY_USERNAME);
return query;
}
});
}
@InjectView(R.id.text) TextView text;
@Override
public View getItemView(final ParseUser user, View v, ViewGroup parent) {
if (v == null) {
v = View.inflate(getContext(), R.layout.adapter_item_friend,
null);
}
super.getItemView(user, v, parent);
ButterKnife.inject(this, v);
text.setText(user.getUsername());
return v;
}
}
I am using a regular fragment containing a ListView in it's layout:
R.layout.yourfriendslistlayout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical" >
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:choiceMode="singleChoice"
android:dividerHeight="1dp" />
</LinearLayout>
The important parts of the code in the fragment:
@Override
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
mAdapter = new ParseUserFriendsAdapter(getActivity());
super.onCreate(savedInstanceState);
}
@InjectView(R.id.listview) ListView mListView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.yourfriendslistlayout, container, false);
ButterKnife.inject(this, rootView);
/** Setting the list adapter for the ListFragment */
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Now it is easy to get the ParseObject that is clicked
ParseUser friend = mAdapter.getItem(position);
Toast.makeText(getActivity(), "clicked " + friend.getObjectId(), Toast.LENGTH_SHORT).show();
EventBus.getDefault().postSticky(friend);
Intent intent = new Intent(getActivity(),
FriendsProfileActivity.class);
startActivity(intent);
}
});
return rootView;
}
Optional addition to the fragment code:
/*
*This last part automatically sets the load indicator whenever parse performs a query
*/
private final OnQueryLoadListener<ParseUser> queryListener = new OnQueryLoadListener<ParseUser>() {
@Override
public void onLoaded(List<ParseUser> arg0, Exception arg1) {
getActivity().setProgressBarIndeterminateVisibility(Boolean.FALSE);
}
@Override
public void onLoading() {
getActivity().setProgressBarIndeterminateVisibility(Boolean.TRUE);
}
};
@Override
public void onResume() {
mAdapter.addOnQueryLoadListener(queryListener);
super.onResume();
}
@Override
public void onPause() {
mAdapter.removeOnQueryLoadListener(queryListener);
super.onPause();
}
Simple use a textview in your list item, and populate it with ObjectID of object in getItemView() of your adapter and set its visibility to View.GONE
Then in onItemClickListener, call getText() of this textview.
In this way you can get objectId in your method and pass it along with intent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With