web-dev-qa-db-fra.com

mettre à jour RecyclerView avec Android LiveData

Il existe de nombreux exemples sur la manière de transmettre une nouvelle liste à un adaptateur lors de la modification de LiveData.

J'essaie de mettre à jour une ligne (par exemple, le nombre de commentaires pour post) dans la liste énorme. Il serait stupide de réinitialiser toute la liste pour ne changer qu'un seul champ.

Je suis capable d'ajouter l'observateur onBindViewHolder, mais je ne comprends pas quand dois-je retirer l'observateur

@Override
public void onBindViewHolder(ViewHolder vh, int position) {
    Post post = getPost(position);
    vh.itemView.setTag(post);
    post.getLiveName().observeForever(vh.nameObserver);
    ... 
}
26
Andrew Matuk

Comme @Lyla a dit, vous devriez observer la liste entière en tant que LiveData dans Fragment ou Activity, lorsque vous recevez des modifications, vous devez définir la liste entière sur l'adaptateur de DiffUtil.

Faux code:

PostViewModel {
    LiveData<List<Post>> posts;  // posts comes from DAO or Webservice
}

MyFragment extends LifecycleFragment {
    PostAdapter postAdapter;

    ...

    void onActivityCreated() {
        ...
        postViewModel.posts.observer(this, (postList) -> {
            postAdapter.setPosts(postList);
        }
    }       
}

PostAdapter {
    void setPosts(List<Post> postList) {
        DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {...}
        ...
    }
}
13
Spark.Bao

L'utilisation de DiffUtil peut vous aider à mettre à jour une ligne d'une liste énorme. Vous pouvez ensuite faire en sorte que LiveData encapsule la liste des commentaires au lieu d’un seul commentaire ou attribut d’un commentaire.

Voici un exemple d'utilisation de DiffUtil dans un adaptateur RecyclerView et dans le liste le code d'observation LiveData dans le fragment .

10
Lyla

Utilisez Transformations.switchMap() pour échanger l’objet Post sous-jacent. Ensuite, il n'est pas nécessaire de supprimer et d'ajouter de nouveau des observateurs lorsque la cellule est recyclée.

@Override
public void onBindViewHolder(PostViewHolder vh, int position) {
    Post post = getPost(position);
    vh.bind(post);
}

Puis dans votre classe ViewHolder

public class PostViewHolder extends RecyclerView.ViewHolder {
    private final MutableLiveData<Post> post = new MutableLiveData<>();

    public PostViewHolder(View itemView) {
        super(itemView);

        LiveData<String> name = Transformations.switchMap(post, new Function<Post, LiveData<String>>() {
            @Override
            public LiveData<String> apply(Post input) {
                return input.getLiveName();
            }
        });

        name.observeForever(new Observer<String>() {
            @Override
            public void onChanged(@Nullable String name) {
                // use name
            }
        });
    }

    public void bind(Post post) {
        post.setValue(post);
    }
}
3
tom-pratt