Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting notified when PagedList gets new data

I'm having kind of the same issue as the question here: Not getting notified on PagedList updates

What I did is implemented the paging library for my application. I load a list of data, that can be very large. The webservice returns only 20 items and with a key, you can retrieve the next 20 and so on. Now this works great, the adapter/recyclerview show the first 20 items. Once I scroll down new items are loaded. The problem is that I need to know when new items are loaded and need a reference to those items. I need to add each item to a map view on top of the list. How can I be notified of changes in my pagedlist? I tried using 'addWeakCallback' but I don't seem to understand how that works. I would expect that my Observer on ViewModel would be called each time data is loaded, but my observer is triggered even before data is loaded. The observer is triggered with an empty list, and I just submit that list to my PagedListAdapter. Can someone please clarify all this? Is there something I can do to observer data changes to my pagedList?

Here is some code:

Observer

Observer<PagedList<Result>> resultObserver = new Observer<PagedList<Result>>() {
                    @Override
                    public void onChanged(@Nullable PagedList<Result> results) {
                        if (mResultAdapter == null) {
                            mResultAdapter= new ResultAdapter(getActivity());
                            mResultRecycler.setAdapter(mResultAdapter);
                            mResultAdapter.submitList(results);
                        }
                    }
                };

ViewModel

sourceFactory = new ResultDataSourceFactory(application.getApplicationContext());
PagedList.Config config = new PagedList.Config.Builder()
            .setEnablePlaceholders(false)
            .setPageSize(20)
            .setPrefetchDistance(5)
            .build();
resultList = new LivePagedListBuilder<>(sourceFactory, config).build();

DataSource

@Override
public void loadInitial(@NonNull LoadInitialParams<String> params, @NonNull final LoadInitialCallback<Result> callback) {
    Webservices.loadSearchResponse(url, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            try {
                Response response = parse(response)
                if (response != null) {
                    //Set search seed
                    searchSeed = response .getSearchSeed();
                    callback.onResult(response.getItemsList(), 0, 0);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    });
}

@Override
public void loadAfter(@NonNull LoadParams<String> params, @NonNull final LoadCallback<Response> callback) {
    Webservices.loadSearchResponse(url, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            try {
                Result result = parse(response);
                if (result!= null) {
                    searchSeed = result.getSearchSeed();
                    callback.onResult(result.getItemsList());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    });
}

Thanks in advance for your help!

like image 256
Allinone51 Avatar asked Aug 26 '18 13:08

Allinone51


2 Answers

For people still searching on this, I managed to find a solution. First of all you should load your data synchronously in loadInitial, loadAfter and loadBefore. By doing so your observer will be called at the right time. Plus you can also add a listener on your adapter: adapter.registerAdapterDataObserver() By using both I managed to get notified when data is added to my PagedList.

like image 165
Allinone51 Avatar answered Sep 24 '22 23:09

Allinone51


To complete the @Allinone51's answer. This is an example of how to declare an AdapterDataObserver :

val defaultObserver = object : AdapterDataObserver() {
    override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
        super.onItemRangeInserted(positionStart, itemCount)
            //code here     
    }

    override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
        super.onItemRangeRemoved(positionStart, itemCount)
            //code here    
    }

    //override fun onItemRangeChanged(positionStart: Int, itemCount: Int) 
    //override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) 
    //override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int)
    //override fun onChanged() 
}

adapter.registerAdapterDataObserver(defaultObserver)
like image 27
Thomas Pires Avatar answered Sep 22 '22 23:09

Thomas Pires