0

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.whereLessThanOrEqualTo("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?

Martin Erlic
  • 5,467
  • 22
  • 81
  • 153
  • There's a field associated with every parse row called created at. I think you can create a query which compares and fetches the rows which have been created before that date, since you already have the previous data. Let me know if it helps. – Alok Omkar Oct 05 '16 at 05:01
  • Check this out : https://www.parse.com/questions/android-api-query-to-get-all-objects-created-today – Alok Omkar Oct 05 '16 at 05:05
  • Okay and then add the new data to my existing adapter? – Martin Erlic Oct 05 '16 at 06:47
  • Yes, that should achieve your objectives. Append the new data from the first index. – Alok Omkar Oct 05 '16 at 07:49

1 Answers1

-1

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();
                }

            }
        });
    }
Alok Omkar
  • 628
  • 1
  • 9
  • 18
  • Would the date parameter have to be created in onCreate and stored as a global preference to be accessed later? Because you'd want the date to be from the moment the user first sees the list objects. – Martin Erlic Oct 05 '16 at 08:03
  • I feel like the date value would have to be updated dynamically (at the end of each query, and returned), or else you'd get many multiples of the same objects. – Martin Erlic Oct 05 '16 at 08:16
  • Please do explain the negative vote. Yes, you'll have to keep track of the date from which you'd need the data to be fetched. That would be available to you the very first time you query parse without any date. That's the significance of null check. – Alok Omkar Oct 05 '16 at 16:21
  • I would also have to adjust the list somehow by the number of new objects or else it will override them and the positioning will be wrong. – Martin Erlic Oct 05 '16 at 16:22
  • You can optionally have recyclerview list things in reverse order. It's an inbuilt feature which comes with linearLayoutManager(), set second parameter to true to list things in reverse. http://stackoverflow.com/a/27727398/2648035 – Alok Omkar Oct 05 '16 at 16:26