android - usar - Soporte RecyclerView no muestra nada hasta que se tocó
son los elementos qué construyen un recyclerview (3)
Estoy usando el soporte RecyclerView en mi aplicación, y veo lo más extraño. No muestra ningún elemento hasta que toco para desplazarse. Entonces, de repente, el RecyclerView se rellena solo. He verificado que la lista que respalda el adaptador está llena y que onCreatViewHolder y onBindViewHolder nunca se invocan hasta que se produce un evento táctil.
Así es como configuré la vista de reciclador:
@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);
}
Aquí hay una esencia de mi adaptador:
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();
}
}
Aquí está el archivo de diseño:
<?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>
Estoy usando recyclerview-v7: 21.0.3 ejecutándose en un Moto X con la versión 4.4.4.
EDITAR: el desplazamiento suave al final de onPostExecute parece resolver el problema:
if (mInboxList.getAdapter().getItemCount() > 0) {
mInboxList.smoothScrollToPosition(0);
}
Es más probable porque no está llamando a los métodos de notificación correctos de RecyclerView.Adapter. Tiene una interfaz mucho más granular para esto de la que tenía anteriormente en ListAdapters. Por ejemplo, en addAll () debe llamar a notifyItemRangeInserted(oldConversationsSize, conversations.size())
lugar de notifyDataSetChanged
Si alguien más está teniendo este problema usando RxJava y Retrofit, resolví este problema agregando el .observeOn(AndroidSchedulers.mainThread())
en mi cadena de métodos antes de suscribirme. Había leído que esto se había solucionado de forma predeterminada, y por lo tanto no explícitamente necesario, pero supongo que no. Espero que esto ayude.
Ejemplo:
public void loadPhotos() {
mTestPhotoService.mServiceAPI.getPhotos()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(photoList -> mRecyclerActivity.OnPhotosLoaded(photoList));
}
Tendría que ejecutar las cosas que hace en onPostExecute en el subproceso UI para que RecyclerView se vuelva a dibujar. Es por eso que el desplazamiento suave funciona porque se ejecuta en el subproceso de interfaz de usuario y, por lo tanto, hace que la vista se vuelva a dibujar.