Tengo dos adaptadores:

private StreamingNowAdapter mStreamingNowAdapter;
private UserStreamingNowAdapter mUserStreamingNowAdapter;

Cuando los cargo con matrices

mStreamingNowAdapter = new StreamingNowAdapter(mEventId, mEventName, 
mEventPreview, mNumberViewers, mContext);

mUserStreamingNowAdapter = new UserStreamingNowAdapter(mUserId, 
mUsername, mProfilePic, mStreamingUserNumberViewers, mContext);

Y llamar a notifyDataSetChanged (); ¿Cómo es que cuando llamo a este método en un adaptador, ambos adaptadores se notifican y se muestran?

Solo llamé al método en el primer adaptador

mStreamingNowAdapter.notifyDataSetChanged();

Y carga mis datos en mi segundo reciclador mUsersStreamingNowAdapter sin que llame a notifyDataSetChanged en el segundo adaptador.

¿Es esto un error o se supone que es así?

Edición1 : dos vistas de reciclador independientes, ambos adaptadores conectados a sus propios recicladores.

RecyclerView mRecyclerViewStreaming = 
view.findViewById(R.id.fraghome_recycler_streaming_now);

RecyclerView mRecyclerViewFollowing = 
view.findViewById(R.id.fraghome_recycler_followed_users);

mRecyclerViewStreaming.setLayoutManager(new 
LinearLayoutManager(getContext()));

mRecyclerViewFollowing.setLayoutManager(new 
LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));

mRecyclerViewStreaming.setAdapter(mStreamingNowAdapter);
mRecyclerViewFollowing.setAdapter(mUserStreamingNowAdapter);

Verifiqué el diseño varias veces para asegurarme de que las identificaciones de la vista de reciclaje no sean idénticas. Todavía no puedo entender por qué está sucediendo esto.

0
DIRTY DAVE 25 sep. 2019 a las 16:21

1 respuesta

La mejor respuesta

Un RecyclerView administrado correctamente y su artefacto requerido (un Adaptador, sus datos, etc.) no deberían interferir con otro RecyclerView administrado correctamente o cualquier otro componente por lo que vale.

Desafortunadamente, el código compartido que proporcionó no es suficiente para determinar qué podría estar sucediendo en su proyecto.

Hasta donde yo sé, los adaptadores RecyclerView no se comunican entre sí de ninguna manera, por lo que un notifyDataSetChanged() en un adaptador no debería tener ningún impacto en otro adaptador, independientemente de dónde se declaren dichos adaptadores (suponiendo que estén diferentes instancias, por supuesto).

Dicho todo esto, te ofreceré mis comentarios personales sobre el código que publicaste. Por favor, no lo tome como algo personal, ya que estoy revisando el código, no el autor, desde un punto de vista puramente técnico basado en mi experiencia con Android.

Fragmento

Inmediatamente me llamó la atención ver que un Fragmento, un componente conocido por ser completamente salvaje en lo que respecta a la administración y el estado del ciclo de vida, tiene muchas responsabilidades.

Comienza por tener no menos de ocho listas de matrices y administrar dos vistas de recicladores y sus respectivos adaptadores, e incluso los LayoutManagers utilizados por las listas.

No contento con tener que administrar todo esto, este Fragmento también necesita manejar una capa de red, manejo de errores (aún no implementado) y almacenamiento de datos (en la memoria por ahora).

Debido a que puede haber reunido esto muy rápido simplemente para ilustrar un caso, dejaré el fragmento en paz por ahora.

Datos

Estás poniendo mucho estrés en tu fragmento y adaptadores al dividir los datos de una manera muy ineficiente. 4 listas de matrices, una por campo? ¿Qué?

             for(HomeFragmentPojo.StreamingNow streamingNow : streamingNowArrayList){
                    mEventId.add(streamingNow.getEvent_id());
                    mEventName.add(streamingNow.getEvent_name());
                    mEventPreview.add(streamingNow.getEvent_preview());
                    mNumberViewers.add(streamingNow.getNumber_viewers());
                }

¿Por qué estás haciendo esto?

Si tiene un objeto StreamingNow que tiene los 4 campos.

¿Por qué no tienes un ListAdapter<StreamingNow, ViewHolder>() que simplemente toma una lista de StreamingNow objetos?

Simplemente puede hacer adapter.submitList(...) para pasar la lista una vez que la obtenga y el adaptador (cuando se cree correctamente) hará lo correcto.

Si alguna vez actualiza la lista, simplemente envíela nuevamente, y el adaptador calculará la diferencia y solo actualizará las filas que deben actualizarse.

El método BIND también es simple, porque se vería así: (pseudocódigo)

viewHolder.eventName = getItem(position).name
viewHolder.viewerCount = getItem(position).viewerCount

//For the image...
Glide.with(mContext)
    .load(getItem(position).preview)
    .apply(RequestOptions.centerCropTransform())
    .into(viewHolder.preview);

...

Tienes la idea.

Según las propiedades que veo, tu "pojo" de StreamingNow se ve así

class StreamingNow {
   String id;
   String name;
   String preview; //maybe an URL? You use Glide so in the bind method, use it.
   String viewerCount;
}

Cuando miro su otro adaptador, veo que tiene los mismos datos ...

Id, nombre, foto, recuento de espectadores.

No es necesario utilizar un adaptador diferente, puede reutilizar el mismo adaptador asumiendo que tienen que comportarse de la misma manera; Si el adaptador de usuarios tiene que hacer algo diferente al hacer clic, por ejemplo, puede pasar la información mínima necesaria para que el adaptador decida qué hacer cuando se hace clic en un elemento. O mejor aún, podría simplemente pasar un Oyente genérico para que el adaptador simplemente llame a "este elemento" X "se hizo clic". Debido a que estos adaptadores no están aquí para tomar decisiones y llamar a las cosas del marco, tienen mucho trabajo en sus placas, y esto no es ni debería ser su responsabilidad.

Quien gestione, cree y mantenga estos adaptadores (hasta ahora, su Fragmento) debería ser el encargado de hacer esto. O incluso mejor aún, un ViewModel o Presentador debería recibir esto y tomar una decisión informada.

En cualquier caso, el evento de clic dentro del adaptador no es el mayor problema aquí, y funcionará de todos modos.

Lo que intento dejar escrito aquí es que su problema es la falta de separación de preocupaciones entre los componentes.

Cuanto más pequeñas y concretas sean tus clases, más fácil será reemplazarlas, probarlas, depurarlas, mejorarlas, etc.

Estás tirando todo tu código en un gran lugar. Si lo separa, es mucho más fácil mantenerlo bajo control.

Entonces, ¿cuál es el problema?

  • Le sugiero que dé un paso atrás, mejore su RecyclerView para usar un ListAdapter
  • No realizaría la solicitud de red en onCreate, sino en onViewCreated o similar, porque durante onCreate en un Fragmento, no hay garantía de que se cree la vista. (¿Recuerdas cuando te dije que los fragmentos eran un fastidio?).
  • Para ser honesto, no tendría ese código de red en el Fragmento; es bastante simple agregar un ViewModel y tener los datos allí. Luego, puede hacer que ViewModel solicite los datos durante onCreate, pero solo obtendrá LiveData de él cuando su ciclo de vida lo permita ... que es el objetivo de LiveData y su observación.
  • Si esto le parece mucho trabajo, también puede serlo, especialmente si es nuevo en Android. Pero valdrá la pena.

¡Buena suerte!

1
Martin Marconcini 26 sep. 2019 a las 17:58