santafebound santafebound - 2 months ago 9
Android Question

How can I query for only new data (Parse/Android)?

I have the following method that queries a list of items in the onCreate method of my main activity and sets them to my adapter:

private void retrieveYeets() {
String groupId = ParseUser.getCurrentUser().getString("groupId");
ParseQuery<ParseObject> query = new ParseQuery<>(ParseConstants.CLASS_YEET);
query.whereContains(ParseConstants.KEY_GROUP_ID, groupId);
query.orderByDescending("lastReplyUpdatedAt");
query.setLimit(1000);
query.findInBackground((yeets, e) -> {

if (mSwipeRefreshLayout.isRefreshing()) {
mSwipeRefreshLayout.setRefreshing(false);
}

if (e == null) {

// We found messages!
mYeets = yeets;
/*System.out.println(yeets);*/

FeedAdapter adapter = new FeedAdapter(getContext(), yeets);
adapter.setHasStableIds(true);
mRecyclerView.setHasFixedSize(true);
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
}
});
}


In the onBindViewHolder, I have a method that retrieves additional data from a pointer, including username, full name, and profile picture of the post author:

private void downloadProfilePicture(ViewHolder holder, ParseObject yeet) {
ParseQuery<ParseUser> query = ParseUser.getQuery();
query.whereEqualTo(ParseConstants.KEY_OBJECT_ID, yeet.getParseObject(ParseConstants.KEY_SENDER_AUTHOR_POINTER).getObjectId());
query.findInBackground((user, e) -> {
if (e == null) for (ParseObject userObject : user) {

if (userObject.getParseFile("profilePicture") != null) {
String profilePictureURL = userObject.getParseFile("profilePicture").getUrl();

// Asynchronously display the profile picture downloaded from Parse
if (profilePictureURL != null) {

Picasso.with(mContext)
.load(profilePictureURL)
.networkPolicy(NetworkPolicy.OFFLINE)
.placeholder(R.color.placeholderblue)
.fit()
.into(holder.profilePicture);

} else {
holder.profilePicture.setImageResource(Integer.parseInt(String.valueOf(R.drawable.ic_profile_pic_add)));
}
}

if (!(userObject.getString(ParseConstants.KEY_AUTHOR_FULL_NAME).isEmpty())) {
holder.fullName.setText(userObject.getString(ParseConstants.KEY_AUTHOR_FULL_NAME));
} else {
holder.fullName.setText("Anonymous Lose");
}

holder.username.setText(userObject.getString(ParseConstants.KEY_USERNAME));

}
});
}


The important part follows: retrieveYeets() is called on SwipeRefreshLayout refresh. So whenever I refresh, I'm retrieving all the data all over again.

Just look at Twitter's UI on refresh to see what I mean. I only want to retrieve new data that hasn't been fetched yet and add that to the top of my adapter. Otherwise, I'm executing unnecessary queries, and the profile pictures, usernames, and full names flash all over the feed because they're being re-downloaded with a new query on every refresh.

Objectives:


  • Query for objects after date of last created object

  • Append only new data to existing adapter



Update:

private void refreshYeets(Date date, FeedAdapter adapter) {
String groupId = ParseUser.getCurrentUser().getString("groupId");
ParseQuery<ParseObject> query = new ParseQuery<>(ParseConstants.CLASS_YEET);
query.whereContains(ParseConstants.KEY_GROUP_ID, groupId);
query.orderByDescending("lastReplyUpdatedAt");
if (date != null)
query.whereGreaterThan("createdAt", date);
query.setLimit(1000);
query.findInBackground((yeets, e) -> {

if (mSwipeRefreshLayout.isRefreshing()) {
mSwipeRefreshLayout.setRefreshing(false);
}

if (e == null) {
// We found messages!
mYeets.addAll(0, yeets); //This should append new messages to the top
/*System.out.println(yeets);*/
if (mRecyclerView.getAdapter() == null) {
adapter.setHasStableIds(true);
mRecyclerView.setHasFixedSize(true);
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
} else {
adapter.notifyDataSetChanged();
}

}
});
}


This works but many of the adapter list objects are replaced and in the wrong positions. What kind of correction would I need to make here? Somehow need to offset by the list by the number of new objects?

Answer

Here's the way you can do it :

private void retrieveYeets(Date date) {
        String groupId = ParseUser.getCurrentUser().getString("groupId");
        ParseQuery<ParseObject> query = new ParseQuery<>(ParseConstants.CLASS_YEET);
        query.whereContains(ParseConstants.KEY_GROUP_ID, groupId);
        query.orderByDescending("lastReplyUpdatedAt");
        if( date != null )
         query. whereGreaterThan("createdAt", date);
        query.setLimit(1000);
        query.findInBackground((yeets, e) -> {

            if (mSwipeRefreshLayout.isRefreshing()) {
                mSwipeRefreshLayout.setRefreshing(false);
            }

            if (e == null) {

                // We found messages!
                mYeets.addAll(0, yeets); //This should append new messages to the top
                /*System.out.println(yeets);*/
                if( mRecyclerView.getAdapter() == null ) {
                mAdapter = new FeedAdapter(getContext(), mYeets);
                mAdapter.setHasStableIds(true);
                mRecyclerView.setHasFixedSize(true);
                adapter.notifyDataSetChanged();
                mRecyclerView.setAdapter(adapter);
                }
                else {
                mAdapter.notifyDataSetChanged();
                }

            }
        });
    }