I'm using the support RecyclerView in my app, and I see the most bizarre thing. It doesn't display any items until I touch to scroll. Then, all of a sudden, the RecyclerView populates itself. I have verified that the list backing the adapter is populated, and that onCreatViewHolder and onBindViewHolder are never called until a touch event.
Here's how I set up the recyclerview:
@Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { Drawable divider = new ColorDrawable(ProfileInfo.getCurrentProfileColor()); mInboxList.addItemDecoration(new DividerItemDecoration(getActivity(), divider, false)); mInboxList.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); mInboxList.setAdapter(new InboxAdapter(getActivity(), new ArrayList<Conversation>())); new AsyncTask<Void, Void, List<Conversation>{ public List<Conversation> doInBackground(...){ //load the conversations return conversations; } public void onPostExecute(List<Conversation> conversations){ ((InboxAdapter) mInboxList.getAdapter()).clear(false); ((InboxAdapter) mInboxList.getAdapter()).addAll(conversations); } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }
Here's a gist of my adapter:
public class InboxAdapter extends RecyclerView.Adapter<InboxAdapter.ViewHolder> { List<Conversation> mConversations; //initialized in contructor @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = mInflater.inflate(R.layout.inbox_item, parent, false); ViewHolder holder = new ViewHolder(v); Log.d(LOG_TAG, "oncreateviewholder : " + viewType); //never called when I first bind the adapter return holder; } @Override public void onBindViewHolder(final ViewHolder holder, int position) { final Conversation item = mConversations.get(position); Log.d(LOG_TAG, "binding " + position); ... } @Override public int getItemCount() { Log.d(LOG_TAG, "item count: " + mConversations.size()); return mConversations.size(); } /** * Empties out the whole and optionally notifies */ public void clear(boolean notify) { mConversations.clear(); if (notify) { notifyDataSetChanged(); } } public void addAll(List<Conversation> conversations) { mConversations.addAll(conversations); notifyDataSetChanged(); } }
Here's the layout file:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="?attr/actionBarSize"> <android.support.v7.widget.RecyclerView android:id="@+id/lv_inbox" android:layout_width="match_parent" android:layout_height="match_parent" ></android.support.v7.widget.RecyclerView> </RelativeLayout>
I'm using recyclerview-v7:21.0.3 running on a Moto X with version 4.4.4.
EDIT: Smooth scrolling at the end of the onPostExecute seems to resolve the issue:
if (mInboxList.getAdapter().getItemCount() > 0) { mInboxList.smoothScrollToPosition(0); }
It's pretty simple, simply set the RecyclerView 's height to wrap_content . That's right.
If anyone else is having this issue using RxJava and Retrofit, I solved this issue by adding the .observeOn(AndroidSchedulers.mainThread())
operator into my method chain before subscribing. I had read this was taken care of by default, and thus not explicitly necessary, but I guess not. Hope this helps.
Example:
public void loadPhotos() { mTestPhotoService.mServiceAPI.getPhotos() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(photoList -> mRecyclerActivity.OnPhotosLoaded(photoList)); }
In my case only this worked:
recyclerView.smoothScrollToPosition(arrayModel.size-1); // I am passing last position here you can pass any existing position
RecyclerView was showing data only when I scroll it. So instead of user to manually scroll I have added above line which will scroll the recyclerView programmatically .
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