Inmersión profunda del adaptador Concat. Obtenga más información sobre ConcatAdapter. | por hongbeom | febrero 2023

Obtenga más información sobre ConcatAdapter.Foto de Homemade Media en UnsplashConcatAdapter es un adaptador que le permite agregar varios adaptadores publicados en RecyclerView: versión 1.2.0-alpha02. En el pasado, para mostrar cada vista en forma de lista, RecyclerView.Adapter tenía que proporcionar un tipo de vista para cada vista. Esto resultó en tener múltiples ViewHolders en un adaptador y combinar múltiples lógicas. ConcatAdapter se implementa para agregar varios adaptadores a un solo adaptador y agregarlos a un solo RecyclerView para beneficiarse de la encapsulación y la reutilización.이미지

Contenidos

configuración

Puede especificar opciones predeterminadas pasando el objeto ConcatAdapter.Config al constructor de ConcatAdapter. Puede controlar los tipos de vista aislados y el modo de Id estable en la configuración, cada uno de los cuales se describe a continuación.

  • aislamientoViewTypes: si es falso, el ConcatAdapter asume que todos los adaptadores asignados a él comparten un grupo de tipo de vista global, por lo que hacen referencia al mismo titular de vista con el mismo tipo de vista. Establecer esta opción en false significa que los adaptadores anidados pueden compartir titulares de vista, pero no deben tener tipos de vista en conflicto que devuelvan el mismo tipo de vista para diferentes titulares de vista. True de forma predeterminada para separar los tipos de vista entre los adaptadores para evitar usar el mismo titular de vista.
  • stableIdMode: hay tres StableIdMode
  1. NO_STABLE_IDS: valor predeterminado; ignora la ID estable del adaptador agregado a concatAdapter. En este modo, si agrega un adaptador que usa una ID estable, se emite una advertencia.

2. ISOLATED_STABLE_IDS: en este modo, hasStableIds() de concatAdapter devuelve verdadero y requiere un adaptador con una ID estable especificada. Debido a que es posible que dos adaptadores diferentes no se reconozcan entre sí y devuelvan la misma ID estable, ConcatAdapter separa el conjunto de ID de cada adaptador, sobrescribe la ID estable devuelta y notifica a RecyclerView nuevamente. En este modo, el valor de RecyclerView.Adapter.getItemId(int) y el valor de RecyclerView.ViewHolder.getItemId() pueden diferir. Además, si agrega un adaptador sin un stableid especificado, se produce un error IlllegalArgumentException.3. SHARED_STABLE_IDS: similar a ISOLATED_STABLE_IDS, hasStableIds() devuelve verdadero y requiere un adaptador con una ID estable. Sin embargo, a diferencia de ISOLATED_STABLE_IDS, no anula el ID estable devuelto. En este modo, los subadaptadores deben conocerse entre sí y no deben devolver el mismo ID a menos que se muevan elementos entre adaptadores. El error IllegalArgumentException ocurre cuando se agrega un adaptador que no tiene una ID estable especificada.

⚠️ Si crea un constructor en ConcatAdapter sin pasar la configuración, se llamará aislarViewTypes como y StableIdMode como

Envoltura de adaptador anidado

La mayoría de las funciones en ConcatAdapter delegan acciones a ConcatAdapterController. Y ConcatAdapterController implementa NestedAdapterWrapper.Callback, así que veamos primero NestedAdapterWrapper. NestedAdapterWrapper es una clase que envuelve el adaptador que agregamos. La devolución de llamada tiene el mismo aspecto que RecyclerView.AdapterDataObserver, pero cuando agregamos el adaptador a través del método addAdapter, el adaptador y el ConcatAdapterController que queremos agregar al parámetro del constructor en NestedAdapterWrapper se pasan, y NestedAdapterWrapper toma la devolución de llamada (ConcatAdapterController) se llama asignación a cualquier método en el AdapterDataObserver que lo tenga como un campo interno. El código anterior muestra que NestedAdapterWrapper tiene un objeto llamado ViewTypeStorage.ViewTypeLookup, StableIdStorage.StableIdLookup como campo. Estos campos determinan el valor devuelto cuando buscamos la identificación o el tipo de vista de un elemento específico en ConcatAdapter.

Tipo de vistaAlmacenamiento

ViewTypeStorage es una interfaz de almacenamiento que almacena y administra tipos de vista. Se mantiene como un campo por el ConcatAdapterController.

getItemViewType

Finalmente, cuando llamamos a la función getItemViewType, el tipo de vista es devuelto por el getItemViewType de NestedAdapterWrapper, que está determinado por la implementación de la interfaz ViewTypeStorage.ViewTypeLookup contenida en el campo. Además, ViewTypeStorage se crea a partir del constructor de ConcatAdapterController, que se divide en dos implementaciones, SharedIdRangeViewTypeStorage se declara según el valor de aislamientoViewTypes.IsolatedViewTypeStorage dentro de WrapperViewTypeLookup, la clase de implementación de la interfaz ViewTypeStorage.ViewTypeLookup, que devuelve el tipo de vista por haciendo referencia al tipo de vista que gestiona la tienda correspondiente.

  • SharedIdRangeViewTypeStorage: getItemViewType devuelve el tipo de vista del adaptador conectado a NestedAdapterWrapper.
  • IsolatedViewTypeStorage: getItemViewType devuelve si ya está guardado; de lo contrario, crea y devuelve un tipo de vista único. (Incluso agregar N adaptadores con el mismo tipo de vista devolverá diferentes tipos de vista únicos para getItemViewType

EstableIdAlmacenamiento

StableIdStorage es una interfaz de almacenamiento que almacena ids estables. De manera similar, el ConcatAdapterController lo contiene como un campo.

getItemId

De manera similar, si NestedAdapterWrapper incluye StableIdLookup como campo y llama a getItemId, ese campo devolverá id. Las implementaciones de StableIdLookup se declaran en tres implementaciones de la interfaz StableIdStorage, cada una de las cuales se comporta de esta manera.

  • NoStableIdStorage: devolver RecyclerView.NO_ID incondicionalmente (predeterminado)
  • SharedPoolStableIdStorage: devuelve el valor getItemId del adaptador sin cambios
  • IsolatedStableIdStorage: si el valor getItemId del adaptador recibido como parámetro ya está almacenado, devuelva el ID o cree un ID único para devolverlo.

agregaradaptador

¿Qué sucede internamente cuando llamamos a addAdapter para agregar un adaptador? El ConcatAdapter llama al addAdapter del ConcatAdapterController y el ConcatAdapterController sigue el siguiente proceso para ejecutar el addAdapter.Controlador – addAdapter

  1. : Cuando pasamos el adaptador y el índice para agregar al addAdapter, primero verificamos si este índice es un valor entre 0 y la cantidad actual de adaptadores. Si intenta agregar un valor de índice fuera de este rango, se produce IndexOutOfBoundsException. Si llama a addAdapter sin pasar el índice, agregue internamente el adaptador en último orden.
  2. : Se produce una excepción cuando StableIdMode del ConcatAdapter actual no es NO_STABLE_IDS y hasStableId del adaptador que está agregando es verdadero. Si StableIdMode es NO_STABLE_IDS y hasStableIds del adaptador que desea agregar es verdadero, se registra la advertencia.
  3. : Si el adaptador ya agregado al ConcatAdapter coincide con el adaptador que desea agregar, devuélvalo sin agregar el adaptador.
  4. Después de completar este proceso, cree un NestedAdapterWrapper, conecte y almacene en caché el adaptador que desea agregar. Además, notifique el RecyclerView que está adjunto al ConcatAdapter mediante el método onAttachedToRecyclerView y, si el elemento ya existe en el adaptador que está agregando, llame a notificationItemRangeInserted para actualizar la lista.
  5. Finalmente, actualice StateRestorationPolicy.

getItemViewType & getItemId

Podemos llamar a getItemViewType desde ConcatAdapter para averiguar el tipo de vista de un elemento de ubicación específico. Luego, el ConcatAdapter llama internamente al getItemViewType del ConcatAdapterController. También puede llamar a getItemId para averiguar el ID de un elemento de ubicación específico. De manera similar, llame a getItemId desde ConcatAdapterController. Hemos visto cómo la llamada getItemViewType y getItemId del contenedor obtiene valores desde arriba, así que veamos findWrapperAndLocalPosition y releaseWrapperAndLocalPosition.

findWrapperAndLocalPosition

findWrapperAndLocalPosition es una función que calcula la posición exacta utilizando la posición global recibida como parámetro. Esto usa la clase WrapperAndLocalPosition definida dentro de ConcatAdapterController. El método findWrapperAndLocalPosition devuelve un objeto WrapperAndLocalPosition con la posición y el contenedor correctos en el siguiente procedimiento.

  1. Si el mReusableHolder almacenado en caché usando el valor de la marca mInUse del campo mReusableHolder mantenido por el controlador no está en uso, cree un nuevo objeto WrapperAndLocalPosition.
  2. Use una declaración recurrente para obtener la lista en caché– Campo para restar el número de elementos en el contenedor almacenado en caché de globalPosition.
  3. Si el número de elementos en el contenedor es mayor que globalPosition, actualice el contenedor y la posición del objeto wrapperAndLocalPosition creado y devuélvalo.

releaseWrapperAndLocalPosition

Si se usó mReusableHolder debido a una acción como getItemId o getItemViewType, se llamará a la función releaseWrapperAndLocalPosition al final. Esto permite devolver el envoltorio y la posición con la menor cantidad posible de asignaciones nuevas. Usar ConcatAdapter, que representa diferentes tipos de datos como un solo adaptador y puede encapsular la lógica, puede ser una buena idea. Sin embargo, si no comprende y utiliza la configuración y el comportamiento interno en detalle, puede producirse un comportamiento no deseado. 🙂

Deja una respuesta

Tu dirección de correo electrónico no será publicada.