3
votes

LiveData, Transformations.map () - Comment forcer le rafraîchissement lorsque l'utilisateur change l'ordre de filtrage?

J'utilise LiveData + Transformations.map () :

private final LiveData<List<Task>> observableTasks;
(...)
observableTasks =  Transformations.map(tasksRepository.getTasks(), tasks-> filterTasks(tasks));

Comment forcer LiveData à rafraîchir? J'ai besoin de Transformations.map () pour préparer une nouvelle liste. Lorsque l'utilisateur modifie les options de filtrage, je dois appeler à nouveau filterTasks (tâches) et afficher une nouvelle liste triée. Les données provenant du référentiel ( tasksRepository.getTasks () ) restent les mêmes.


5 commentaires

Qu'entendez-vous par forcer LiveData à s'actualiser?


En utilisant Private final LiveData > observableTasks = Transformations.map (dataList, this :: addOne); Je peux obtenir de nouvelles valeurs chaque fois que je change les valeurs.


J'ai besoin d'appeler à nouveau filterTasks (tasks) car l'utilisateur a changé l'ordre de filtrage. Les données provenant du référentiel restent les mêmes.


pouvez-vous ajouter du code qui déclenche des changements pour l'ordre de filtrage?


Cela peut être par exemple la fonction changeFilteringOrderTo (EnumFilterOrder enumFilterOrder) , puis filterTasks utilise le champ enumFilterOrder pour décider quoi faire avec la liste.


3 Réponses :


1
votes

Je pense avoir trouvé la solution. J'ai créé un champ LiveData supplémentaire filterChangeEvent . Chaque fois que l'utilisateur change l'ordre de filtrage, la nouvelle valeur est définie sur filterChangeEvent . Ensuite, j'utilise switchMap avec filterChangeEvent comme déclencheur:

    observableTasks = Transformations.switchMap(filterChangeEvent, input -> {
        final MediatorLiveData<List<Tasks>> result = new MediatorLiveData<>();
        result.addSource(tasksRepository.getTasks(), tasks -> result.setValue(filterTasks(tasks)));
        return result;
    });


1 commentaires

Pouvez-vous expliquer pourquoi la carte et pourquoi changer la carte? Je me sens obligé de le comprendre.



1
votes

Sur la base des informations que vous avez fournies, j'ai suivi les étapes suivantes et mon observable a été déclenché comme prévu. Je pense que vous faites quelque chose de mal dans le référentiel ou en classe où vous gérez la transformation. Comme il n'y a pas assez de code à vérifier, j'ai créé mes propres classes factices:

  1. J'ai créé un POJO de tâche factice:
TasksRepository tasksRepository = new TasksRepository();
MyViewModel viewModel = new MyViewModel(tasksRepository);

button.setOnClickListener(v -> tasksRepository.addTask());

viewModel.getObservableTasks().observe(this,
        tasks -> Log.d(TAG, Arrays.toString(new List[]{tasks})));
  1. J'ai créé un référentiel factice contenant LiveData:
public class MyViewModel {
    private final LiveData<List<Task>> observableTasks;

    public MyViewModel(TasksRepository tasksRepository) {
        this.observableTasks = Transformations.map(tasksRepository.getTasks(), this::changeId);
    }

    private List<Task> changeId(List<Task> tasks) {
        List<Task> resultTaks = new ArrayList<>();
        for (Task task : tasks) {
            String newId = "TASK" + task.getId();
            task.setId(newId);
            resultTaks.add(task);
        }
        return resultTaks;
    }

    public LiveData<List<Task>> getObservableTasks() {
        return observableTasks;
    }
}
  1. Classe créée appelée MyViewModel qui peut gérer la transformation. Pendant la transformation, nous ajoutons simplement le préfixe "TEST" à l'ID de la tâche. Vous pouvez le comparer avec votre code et ça devrait aller:
public class TasksRepository {
    private List<Task> taskList = new ArrayList<>();
    private MutableLiveData<List<Task>> _tasks = new MutableLiveData<>();
    private LiveData<List<Task>> tasks = _tasks;

    public TasksRepository() {
        for (int i = 0; i < 5; i++) {
            taskList.add(new Task(createTaskId()));
        }
        _tasks.setValue(taskList);
    }

    private String createTaskId() {
        return UUID.randomUUID().toString();
    }

    public void addTask() {
        taskList.add(new Task(createTaskId()));
        _tasks.setValue(taskList);
    }

    public LiveData<List<Task>> getTasks() {
        return tasks;
    }
}
  1. Ajoutez des données lorsque vous cliquez sur le bouton et observez les changements de données:
public class Task {
    private String id;

    public Task(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @NonNull
    @Override
    public String toString() {
        return "Task id is " +id;
    }
}


2 commentaires

Lorsque l'utilisateur change l'option de filtre, rien ne change dans le référentiel, donc la transformation et filterTasks ne sont pas appelés. Vérifiez ma réponse.


Vous n'avez pas LiveData qui est mis à jour lorsque l'utilisateur change de «filtre»?



0
votes

Checkout Transformation.switchMap. Il explique le cas suivant quand l'utiliser également.)

Scénario:

Dans un scénario où le référentiel contient User (1, "Jane") et User (2, "John"), lorsque la valeur userIdLiveData est définie sur "1", switchMap appellera getUser (1), cela renvoie un LiveData contenant la valeur User (1, "Jane"). Alors maintenant, le userLiveData émettra User (1, "Jane"). Lorsque l'utilisateur du référentiel est mis à jour en User (1, "Sarah"), userLiveData est automatiquement notifié et émet User (1, "Sarah").

Lorsque la méthode setUserId est appelée avec userId = "2", la valeur de userIdLiveData change et déclenche automatiquement une demande pour obtenir l'utilisateur avec l'ID "2" du référentiel. Ainsi, le userLiveData émet User (2, "John"). Le LiveData renvoyé par repository.getUserById (1) est supprimé en tant que source.


0 commentaires