как получить первый или (любой) элемент из списка LiveData в Android MVVM архитектуре? - PullRequest
2 голосов
/ 14 апреля 2020

Я использовал архитектуру MVVM для создания приложения Android с репозиторием в качестве посредника между базой данных ViewModel и Room. В одной из функций я извлекаю список объектов из таблицы в классе репозитория, чтобы я мог вызвать его из класса ViewModel.

как получить первый элемент в списке из класса репозитория вместо наблюдения LiveData в одном из действий?

вот мой класс репозитория:

public class StudentRepository {

private StudentDAO mStudentDAO;
private LiveData<List<Student>> mAllStudents;

public StudentRepository(Application application){
    StudentRoomDatabase db = StudentRoomDatabase.getDatabase(application);
    mStudentDAO= db.StudentDAO();
    mAllStudents= mStudentDAO.getAllStudents();
}



public LiveData<List<Word>> getAllStudents(){

    // What I need to return the first element in the mAllStudents list
    // in order to type the first student name in the Log.d 

Log.d ("First_Name", mAllStudent.get (0)); // Я хочу набрать имя студента в журнале, не добавляя функцию в viewModel, и наблюдать, что в любом упражнении

    return mAllStudents;
}

}

1 Ответ

1 голос
/ 14 апреля 2020

как получить первый или (любой) элемент из списка LiveData в Android архитектура MVVM

Если вы хотите получить определенный элемент из списка LiveData, тогда вы необходимо ограничить запрос смещением.

По умолчанию ограничение запроса не учитывает смещение; поэтому значение смещения по умолчанию равно 0.

Например, в вашем Dao:

Приведенные ниже запросы в Примерах 1 и 2 эквивалентны, поскольку значение смещения по умолчанию равно 0.

Пример

@Query("SELECT * FROM students LIMIT  :limit")
LiveData<List<Student>> getStudents(int limit);

// Query
getStudents(1); // returns the first row of the list

Пример 2

@Query("SELECT * FROM students LIMIT  :limit OFFSET :offset")
LiveData<List<Student>> getStudents(int limit, int offset);

// Query
getStudents(1, 0); // returns the first row of the list

Примечание: Здесь я предполагаю ваше класс модели Student

Это примерно первый ряд; но чтобы вернуть номер строки x, вам необходимо изменить смещение на: x-1, так как смещение равно значению 0

Пример 3 (тот же запрос Дао, что и в Примере 2)

getStudents(1, 1); // returns the second row
getStudents(1, 4); // returns the fifth row

Если вы хотите вернуть более одной строки, вам нужно манипулировать значением LIMIT, чтобы вернуть x строк из результатов, затем ограничьте запрос x.

getStudents(2, 1); // returns the second and third rows
getStudents(3, 4); // returns the fifth, sixth, and seventh rows

Надеюсь, что это ответ на ваш вопрос

Редактировать согласно комментариям

У меня уже есть список, возвращенный другим запросом @Query("SELECT * FROM students) LiveData<List<Student>> getStudents(); Таким образом, возвращаемое значение является списком. Я хочу получить первый элемент из списка. Этот ответ действительно возвращает первый элемент, но мне нужно пройти все шаги (чтобы определить этот метод в классе ViewModel и наблюдать его в MainActivity, чтобы получить список или любой элемент в списке). Что мне нужно, это ввести первое значение в списке, пока я использую функцию в классе репозитория. -

Теперь вы используете запрос ниже

@Query("SELECT * FROM students")
LiveData<List<Student>> getStudents();

И вы хотите:

  1. Получить первый или любой элемент в списке. и сделать это в соответствии с тем, что упомянуто выше.
  2. Пройдите все шаги (чтобы определить этот метод в классе ViewModel и соблюдайте его в MainActivity, чтобы получить список или любой элемент в list).

Для этого:

In Dao: : измените свой запрос на

@Query("SELECT * FROM students LIMIT  :limit OFFSET :offset")
LiveData<List<Student>> getAllStudents(int limit, int offset);

In Репозиторий:

public class StudentRepository {

    ...

    public LiveData<List<Student>> getAllStudents(final int limit, final int offset) {
        return mDAO.getAllStudents(limit, offset);
    }
}

В ViewModel:

public LiveData<List<Student>> getAllStudents(final int limit, final int offset) {
    return mRepository.getAllStudents(limit, offset);
}

В активности:

private void getAllStudents(int limit, int offset) {
    mViewModel.getAllStudents(limit, offset).observe(this, new Observer<List<Student>>() {
        @Override
        public void onChanged(List<Student> students) {
            if (students != null) {
                // Here you can set RecyclerView list with `students` or do whatever you want

            }
        }
    });
}

И чтобы проверить это:

getAllStudents(1, 0); // return first row from the table.
getAllStudents(2, 0); // return first 2 rows from the table.
getAllStudents(2, 1); // return 2nd and 3rd rows from the table.
getAllStudents(-1, 5); // remove first 5 rows from the table.

И вернуть первый элемент в списке mAllStudents, чтобы ввести имя первого студента в Log.d

. , В вашей Деятельности

mViewModel.getAllStudents(1, 0).observe(this, new Observer<List<Student>>() {
    @Override
    public void onChanged(List<Student> students) {
        if (students != null) {
            Student student = students.get(0);
            Log.d("First_Name", student.getName());
        }
    }
});

Редактировать можно ли вернуть любой элемент списка без выполнения всех шагов, таких как написание функции в ViewModel, и наблюдать это в MainActivity? У меня вопрос не в том, чтобы выполнить все шаги.

Да, это возможно, но приведенная выше модель является рекомендованной моделью Google. Вы можете вернуть List<Student> из Dao запроса вместо LiveData<List<Student>>, но плохие новости:

  1. Вы должны обрабатывать это в отдельном фоновом потоке; потому что LiveData делает это бесплатно.
  2. Вы потеряете значение LiveData; поэтому вам нужно вручную обновить список sh, чтобы проверить любое обновление, так как вы не сможете использовать шаблон наблюдателя.

Итак, вы можете опустить ViewModel и Repository и выполните все действия из упражнения следующим образом:

private Executor mExecutor = Executors.newSingleThreadExecutor();

public void getAllStudents(final int limit, final int offset) {

    final StudentDAO mDAO = StudentDatabase.getInstance(getApplicationContext()).getStudentDAO();

    mExecutor.execute(new Runnable() {
        @Override
        public void run() {
            List<Student> students = mDAO.getAllStudents(limit, offset);
            Student student = students.get(0);
            Log.d("First_Name", student.getName());
        }
    });
}

// Usage: getAllStudents(1, 0);

И запрос для Дао:

@Query("SELECT * FROM students LIMIT  :limit OFFSET :offset")
List<Student> getAllStudents(int limit, int offset);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...