web-dev-qa-db-fra.com

Je veux que mon RecyclerView ne recycle pas certains éléments

J'utilise une RecyclerView avec des vues hétérogènes à l'intérieur, comme on le voit dans ce tutoriel .

J'ai dans le RecyclerView des articles qui sont aussi des RecyclerViews. Trop difficile à imaginer? Supposons que je veuille copier la présentation du Play Store: Un grand RecyclerView avec une présentation linéaire verticale et rempli de nombreux éléments: applications uniques et carrousel d'applications.

Si l'élément à ajouter est la mise en page d'une seule application, l'ID 1 sera utilisé et j'ajouterai la mise en page d'un seul élément . Sinon, si j'ai besoin d'ajouter un carrousel, je vais ajouter un élément à l'élément principal RecyclerView: Un autre RecyclerView avec son propre adaptateur.

Ça marche très bien. Sauf lorsque vous faites défiler le RecyclerView principal. Pourquoi? Parce que certaines vues sont détruites lorsqu'elles ne sont plus visibles, puis recréées dans la méthode onBindViewHolder(). Pourquoi ici? Parce que l'adaptateur de RecyclerView principal passe pour la position X et appelle ensuite OnBindViewHolder(). Ce dernier crée alors un nouveau RecyclerView avec son propre adaptateur et l’assigne. J'aimerais garder ces points de vue simplement parce qu'ils sont lourds à regonfler à chaque fois. 

Est-ce possible? Si oui, pouvez-vous me dire comment?

15
Joaquin Iurchuk

Utilisez ceci:

recyclerView.getRecycledViewPool().setMaxRecycledViews(TYPE_CAROUSEL, 0);

Ce ne sera pas recycler une vue viewType TYPE_CAROUSEL mais si le nombre d'éléments de ce type est très élevé, il réduira vos performances de manière significative, peut-être même causer Oomes

MODIFIER

Après avoir lu la réponse de MML13, je pense que cela pourrait fonctionner pour vous. Vous êtes inquiet au sujet des articles de votre carrousel étant regonflé lorsque ce point de vue est rebinded dans RecyclerView extérieur. Si tous ces sont de carrousel pour un même type, à savoir, ils utilisent tous même adaptateur, vous pouvez garder l'adaptateur à l'intérieur de ViewHolder RecyclerView extérieur, et juste échanger les données et appeler notifyDataSetChanged() ou notifyItemRangeChanged(...) sur cet adaptateur quand il est rebinded. Cela recyclera toutes les vues du carrousel et toutes les vues à l'intérieur de ces carrousels.

49
Sourabh

Vous pouvez également définir le code ci-dessous dans votre méthode d'adaptateur onBindViewholder ().

holder.setIsRecyclable(false);

J'ai pris référence à ce lien

http://aphoe.com/blog/prevent-androids-recyclerview-recycling-views/

13
Nancy Y

Parce que certaines vues sont détruites quand elles ne sont plus visibles et ensuite recréé dans la méthode onBindViewHolder ().

Ce n'est pas vrai, ils ne sont pas créés à nouveau, ils se rebindent. si vous avez une vue pour la position X (dans la ferraille ou le recycleur) RecyclerView l'utilisera et la reliera.

J'aimerais garder ces points de vue simplement parce qu'ils sont lourds à regonfler à chaque fois.

La variable principale RecyclerView les conserve pour vous. Il vous suffit de modifier les données de l’adaptateur de votre seconde RecyclerView et d’appeler notifyDataSetChanged. Stockez également votre deuxième adaptateur RecyclerView dans la viewHolder de votre RecyclerView principale.

8
user5703518

Vous pouvez ajouter dans votre adaptateur:

@Override
public void onBindViewHolder(final CommentViewHolder viewHolder, final int position) {
    viewHolder.setIsRecyclable(false);
}

Indique au recycleur si cet article peut être recyclé. Les vues non recyclables ne seront pas réutilisées pour d'autres éléments jusqu'à ce que setIsRecyclable() soit ultérieurement défini sur true. Les appels à setIsRecyclable() doivent toujours être associés (un appel à setIsRecyclabe(false) doit toujours être associé à un appel ultérieur à setIsRecyclable(true)). Les paires d'appels peuvent être imbriquées, car l'état est compté en interne.

4
Osmar I. Cancino

Mon code fonctionne pour la réinitialisation de l'interface utilisateur dans recycleview.

public class BooleanViewHolder extends BaseViewHolder<ConfigItemBoolean> {
    private SwitchCompat configBoolean;

    BooleanViewHolder(View view) {
        super(view);
        configBoolean = view.findViewById(R.id.enable_config_boolean);
        configBoolean.setOnCheckedChangeListener((buttonView, isChecked) -> {
            ((ConfigItemBoolean) getItem(getAdapterPosition())).setValue(isChecked);
            DataSet.mConfigDataSet.getConfigItemBooleanMap().put(configPairList.get(getAdapterPosition()).first, ((ConfigItemBoolean) getItem(getAdapterPosition())));
        });
    }

    @Override
    void bind(ConfigItemBoolean item, String key) {
        configBoolean.setText(item.getDisplayName());
        configBoolean.setChecked(item.isValue());
    }

}
0
May Yamin Thant