Nano Hash - криптовалюты, майнинг, программирование

При установке флажка он обновляет другие строки в recyclerview. DiffUtils и DataBinding, используемые для обновления и привязки данных.

Я пытаюсь реализовать приложение для создания задач. Пользователь должен иметь возможность проверить задачу, чтобы отметить ее как выполненную. Но когда в recyclerview установлен флажок более чем одного зрителя, он начинает обновлять другие строки. Предположим, у меня есть 3 строки - A,B,C , я устанавливаю флажок A, и когда я устанавливаю флажок B, начинают происходить странные вещи, заголовок строки A изменился на и теперь у меня есть 2 элемента с заголовком B. И когда я снимаю флажок B, он также снимает флажок A. Итак, вот мой код. Этот беспорядок прекращается, когда в методе equals я удаляю проверку Object.equals(completed, task.completed). Но в этом случае не вызывается функция setStyle, отвечающая за отрисовку обводки на текстовом поле.


@Entity(tableName = "tasks")
public class Task {
    @ColumnInfo(name = "title")
    String title;

    public String getDescr() {
        return descr;
    }

    @ColumnInfo(name = "description")
    String descr;
    @ColumnInfo(name = "completed")
    boolean completed = false;

    @ColumnInfo(name = "task_date")
    String taskDate;
    @ColumnInfo(name = "task_deadline")
    String taskDeadline;


    @NonNull
    @PrimaryKey
    @ColumnInfo(name = "taskId")
    String id;

    public Task(String title, String descr, boolean completed) {
        this.title = title;
        this.descr = descr;
        this.completed = completed;
        id = UUID.randomUUID().toString();
    }

    public Task(String title, String descr, String date, boolean completed) {
        this.title = title;
        this.descr = descr;
        this.completed = completed;
        this.taskDate = date;
        id = UUID.randomUUID().toString();
    }


    public Task(String title, String descr, String date, String time, boolean completed) {
        this.title = title;
        this.descr = descr;
        this.completed = completed;
        this.taskDate = date;
        this.taskDeadline = time;
        id = UUID.randomUUID().toString();
    }

    public boolean isEmpty() {
        return title.isEmpty() || descr.isEmpty();
    }

    public boolean isActive() {
        return !completed;
    }

    public boolean isCompleted() {
        return completed;
    }

    @NonNull
    public String getId() {
        return id;
    }


    public String getTaskDeadline() {
        return taskDeadline;
    }

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

    public String getTitle() {
        return title != null ? title : descr;
    }

    public String getTaskDate() {
        return taskDate != null ? taskDate : "";
    }

    @Override
    public boolean equals(@Nullable Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Task task = (Task) o;
        return Objects.equals(id, task.id) && Objects.equals(title, task.title) &&
                Objects.equals(descr, task.descr) && Objects.equals(completed, task.completed);
    }
}


открытый класс TasksAdapter расширяет ListAdapter {

private ItemTaskBinding binding;
private final TaskViewModel mViewModel;

TasksAdapter(TaskViewModel viewModel) {
    super(DIFF_CALLBACK);
    mViewModel = viewModel;
}

@NonNull
@Override
public TaskViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
    binding = ItemTaskBinding.inflate(layoutInflater, parent, false);
    return new TaskViewHolder(binding);
}

@Override
public void onBindViewHolder(@NonNull TaskViewHolder holder, int position) {
    Task item = getItem(position);
    holder.bind(mViewModel, item);
}

class TaskViewHolder extends RecyclerView.ViewHolder {
    private TaskViewHolder(ItemTaskBinding binding) {
        super(binding.getRoot());
    }

    void bind(TaskViewModel viewModel, Task item) {
        binding.setViewModel(viewModel);
        binding.setTask(item);
        binding.executePendingBindings();
    }
}

private static final DiffUtil.ItemCallback<Task> DIFF_CALLBACK = new DiffUtil.ItemCallback<Task>() {

    @Override
    public boolean areItemsTheSame(@NonNull Task oldItem, @NonNull Task newItem) {
        return oldItem.getId().equals(newItem.getId());
    }

    @Nullable
    @Override
    public Object getChangePayload(@NonNull Task oldItem, @NonNull Task newItem) {
        return super.getChangePayload(oldItem, newItem);

    }

    @Override
    public boolean areContentsTheSame(@NonNull Task oldItem, @NonNull Task newItem) {
        return  oldItem.equals(newItem);
    }
};

}

А это XML

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <import type="android.widget.CompoundButton" />

        <variable
            name="viewModel"
            type="com.example.taskmanagement.tasks.TaskViewModel" />

        <variable
            name="task"
            type="com.example.taskmanagement.room.Task" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/rounded_border_white"
        android:onClick="@{() -> viewModel.openTaskToUpdate(task)}"
        android:paddingLeft="12dp"
        android:paddingRight="12dp"
        android:paddingEnd="12dp"
        android:paddingStart="12dp"
        android:paddingBottom="8dp"
        android:layout_marginBottom="8dp">

        <CheckBox
            android:id="@+id/completed_checkBox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:checked="@{task.completed}"
            android:onClick="@{(view) -> viewModel.completeTask(task, ((CompoundButton)view).isChecked())}"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_marginTop="10dp"/>


        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="15dp"
            android:layout_marginLeft="15dp"
            android:text="@{task.title}"
            android:textAppearance="@style/TextAppearance.AppCompat.Title"
            app:completedTask="@{task.completed}"
            app:layout_constraintStart_toEndOf="@+id/completed_checkBox"
            app:layout_constraintTop_toTopOf="@id/completed_checkBox"
            android:layout_marginEnd="5dp"
            android:layout_marginRight="5dp"
            tools:text="aaaaaaaaaaa" />

        <TextView
            android:id="@+id/description"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{task.descr!=null? task.descr : "" }'
            app:layout_constraintStart_toStartOf="@id/title"
            app:layout_constraintTop_toBottomOf="@id/title"
            tools:text="aaaaaaaaa" />

        <TextView
            android:id="@+id/task_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:text="@{task.taskDeadline}"
            app:layout_constraintStart_toEndOf="@id/task_date"
            app:layout_constraintTop_toTopOf="@id/task_date"
            tools:text="15:30" />

        <TextView
            android:id="@+id/task_date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="5dp"
            android:drawableLeft="@drawable/choose_date_resized"
            android:drawablePadding="5dp"
            android:text="@{task.taskDate}"
            app:layout_constraintStart_toStartOf="@id/completed_checkBox"
            app:layout_constraintTop_toBottomOf="@id/description"
            tools:text="12/16/2020" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>



Это модель просмотра


    private static TasksRepository mTaskRepository;
    private static MutableLiveData<List<Task>> allItemsMutableLiveData = new MutableLiveData<>();
    private static MutableLiveData<List<Task>> completedItemsMutableLiveData = new MutableLiveData<>();

    private MutableLiveData<Event<String>> _isTaskClicked = new MutableLiveData<>();
    private static List<Task> listOfTasks;
    private static List<Task> listOfCompletedTasks;

    private static final CompositeDisposable mDisposable = new CompositeDisposable();


    LiveData<Event<String>> getIsTaskClicked() {
        return _isTaskClicked;
    }

    TaskViewModel(TasksRepository taskRepository) {
        mTaskRepository = taskRepository;
        getListOfTasks();
    }

    public void openTaskToUpdate(Task task) {
        _isTaskClicked.setValue(new Event(task.getId())); // Trigger the event by setting a new Event as a new value
    }

    private static void getListOfTasks() {
        mDisposable.add(mTaskRepository.getAllTasksFromDB().map(taskList -> {
                    listOfTasks = taskList;
                    return listOfTasks;
                }).observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Consumer<List<Task>>() {
                            @Override
                            public void accept(List<Task> taskList) throws Exception {
                                allItemsMutableLiveData.setValue(taskList);
                            }
                        })
        );
    }

    public static LiveData<List<Task>> getItems() {
        if (allItemsMutableLiveData.getValue() != null) {
            for (int i = 0; i < allItemsMutableLiveData.getValue().size(); i++) {
                Timber.d("task" + i + allItemsMutableLiveData.getValue().get(i).getTitle());
            }
        }
        return allItemsMutableLiveData;

    }

    void getAllActiveTasks() {
        mDisposable.add(mTaskRepository.getAllActiveTasks().subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<List<Task>>() {
                    @Override
                    public void accept(List<Task> taskList) throws Exception {
                        allItemsMutableLiveData.setValue(taskList);
                    }
                }));
    }

    public static LiveData<List<Task>> getCompletedItems() {
        mDisposable.add(mTaskRepository.getAllCompletedTasks()
                .observeOn(Schedulers.io()).map(taskList -> {
                    listOfCompletedTasks = taskList;
                    return listOfCompletedTasks;
                }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<List<Task>>() {
                    @Override
                    public void accept(List<Task> taskList) throws Exception {
                        completedItemsMutableLiveData.setValue(listOfCompletedTasks);
                    }
                }));

        return completedItemsMutableLiveData;
    }

    void deleteAllTasks() {
        mDisposable.add(Completable.fromAction(new Action() {
            @Override
            public void run() throws Exception {
                mTaskRepository.deleteAllTasks();
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe());
    }


    public void completeTask(Task task, Boolean isChecked) {
        if (isChecked) {
            mDisposable.add(Completable.fromAction(() -> mTaskRepository.completeTask(task.getId(), true))
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread()).subscribe());
        } else {
            mDisposable.add(Completable.fromAction(() -> mTaskRepository.activateTask(task.getId()))
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread()).subscribe());
        }
    }


    @Override
    protected void onCleared() {
        mDisposable.clear();
        super.onCleared();
    }
}

  • Я думаю, вам нужно изменить свою реализацию. В вашей модели данных Task должно быть поле isChecked, когда оно выбрано, установите его true, unselected, установите false. И в вашем методе areContentsTheSame() должен быть oldItem.isSelected.equals(newitem.isSelected). Таким образом, заполнение данных будет согласованным и будет обновляться с использованием diffutils при изменении содержимого. Еще одна причина сохранить это в модели, чтобы сохранить состояние отмеченного элемента, предположим, вы проверяете элемент, затем прокручиваете recycelrview вниз, затем снова возвращаетесь к этому элементу, его отмеченное состояние будет потеряно. 25.04.2020
  • У меня есть метод isCompleted(), который делает то, что вы только что описали. Часть флажка работает по назначению. Когда я добавляю проверку условия флажка в методе areContentsTheSame(), начинается беспорядок. Как вы можете видеть в модели данных, у меня есть переопределенный метод equals(), где последняя проверка относится к условию флажка. 25.04.2020
  • Вы можете опубликовать код модели просмотра здесь 25.04.2020
  • @akashzincle Я добавил это. 25.04.2020
  • В флажке вы вызываете viewModel.completeTask по щелчку, вместо этого вы можете попробовать один раз проверить на Cangelistner, это может помочь. Для прослушивателя изменения флажка в привязке данных вы можете обратиться по этой ссылке stackoverflow.com/a/37288929/3497972 25.04.2020

Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..