8
votes

Meilleure pratique pour supprimer asynchroneusement un élément de listeView / recyclerview

J'ai un listview avec un cursorloader . L'utilisateur peut ouvrir des éléments listview (ouvrir un autre fragment ) ou supprimer des éléments. Toutes les actions de base de données se produisent de manière asynchrone et généralement une fraction d'une seconde. Mais techniquement, l'utilisateur pourrait supprimer un élément puis ouvrir l'élément avant le rappel et la cause de la suppression. Quelle est la meilleure façon de gérer cela? Voici les options que je vois.

  1. suppose simplement que le asynccttask se produira toujours assez rapidement pour éviter un problème
  2. Faites l'opération de base de données sur le fil d'interface utilisateur
  3. Invallamez le listview avant le asyncccTask (mais cela provoquerait un éclair dans l'interface utilisateur)
  4. Bloquer la saisie de l'utilisateur en quelque sorte pendant le AsynccTask

    edit: j'ai fini par utiliser recyclerview mais je ne peux pas appeler adapter.notifyItemReMoved (itemPos) jusqu'à après avoir supprimé l'article de la base de données.


0 commentaires

3 Réponses :


3
votes
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private List<String> items = new ArrayList<>(
            Arrays.asList("first", "second", "third"));

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RecyclerView myRecyclerView = (RecyclerView)
                findViewById(R.id.my_recycler_view);
        myRecyclerView.setAdapter(new MyAdapter());
    }

    private class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new MyViewHolder(LayoutInflater.from(MainActivity.this)
                    .inflate(R.layout.my_item, parent, false));
        }

        @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {
            holder.bind(position);
        }

        @Override
        public int getItemCount() {
            return items.size();
        }

        public class MyViewHolder extends RecyclerView.ViewHolder {

            private TextView valueTextView;
            private Button deleteButton;

            public MyViewHolder(View itemView) {
                super(itemView);
                valueTextView = (TextView) itemView.findViewById(R.id.value_text);
                deleteButton = (Button) itemView.findViewById(R.id.delete_button);
                deleteButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        int position = (int) v.getTag();
                        items.remove(position);
                        notifyItemRemoved(position);
                        notifyItemRangeChanged(position, items.size());
                    }
                });
            }

            public void bind(int position) {
                valueTextView.setText(items.get(position));
                deleteButton.setTag(position);
            }
        }
    }
}

2 commentaires

La désactivation de la vue supposerait que l'élément n'est pas et ne sera pas lié à une autre vue, non? Pourriez-vous me signaler aux méthodes de clé que je devrais regarder dans RecyclerView? Cela ressemble à une option intéressante si elle n'est pas trop compliquée.


C'est en fait super-facile :) Il suffit d'ajouter du code à ma réponse.



6
votes

meilleure option dans votre cas utilisera recyclerview . Parce que lorsque vous avez cliqué sur Supprimer, vous pouvez appeler Adapter.notifyItemRemrotemReMoved (itemPos) . Donc, l'élément de liste sera supprimé avec l'animation de votre recyclerview et vous ne vous inquiétez pas du résultat de l'opération DELETE.

Voir le didacticiel de développeur Android sur crée des listes et des cartes :

Utilisez le recyclerview widget lorsque vous avez des collections de données dont Les éléments changent au moment de l'exécution en fonction de l'action utilisateur ou des événements réseau.

Voici un exemple: xxx


7 commentaires

N'oubliez pas de mdataseet.remove (position) et de notifyItemRangéChanged (position, mdataset.Size ()). Sans ce dernier, vous aurez des crash lors de la suppression du premier élément jusqu'à ce que la liste soit vide.


Et si j'utilise un curseur? Je ne peux pas retirer l'élément du jeu de données avant d'avoir un nouveau curseur.


Vous n'avez pas besoin d'attendre votre nouveau CusOSR. Il suffit de supprimer l'élément de votre RecyclerVoir d'abord. NOTIFYITEMREMOWED accepte la position de paramètre. Donc, passez simplement la position de l'endroit où vous avez cliqué sur le bouton Supprimer. Je veux dire que vous n'avez pas besoin de mettre votre notifiantemReMoved après avoir obtenu votre nouveau curseur. Modifiez d'abord la priorité et appelez notification NotyItemremivié ne regarde pas vos données, elle supprime uniquement votre élément de vue Recycler de votre liste. Ensuite, vous pouvez également supprimer vos données de votre DB @cambunctious.


J'ai essayé et ça ne marche pas. La documentation est très claire que notifyItemRemoved est d'avertir l'adaptateur que l'élément a été supprimé à partir du jeu de données


Ok, juste une autre idée, je suppose que vous pouvez créer POJO pour vos jeux de données de base de données, et vous pouvez créer votre adaptateur pour afficher le contenu à partir de la liste , vous pouvez facilement supprimer vos données de votre liste et peut mettre à jour UI rapidement. Je veux dire que vos codes seront ressemblons à ceux-ci; myList.remove (itemPos) , notifierItemRemoved (itemPos) , db.deleterecord (itemPos)


Avez-vous vérifié cette méthode @Cambunctious?


La solution RECYCLERVIEW doit être acceptée Réponse. NotifyDataSetSetSetched () et une autre méthode de notification est si bonne lorsque vous travaillez avec la liste des articles.



0
votes

Si votre requête de base de données ne renvoie pas beaucoup de données , il n'y a pas de problème à faire des opérations de base de données sur le fil de l'interface utilisateur.


1 commentaires

Cela se trouve être probablement vrai dans mon cas, mais je suis hésitant à l'adopter. La quantité de données dépend du nombre d'éléments créés par l'utilisateur. De plus, la quantité de données peut facilement augmenter lorsque l'application évolue.