SQLite
 sql >> Base de Dados >  >> RDS >> SQLite

como obter o primeiro ou (qualquer) elemento de uma lista LiveData na arquitetura Android MVVM?


como obter o primeiro ou (qualquer) elemento de uma lista LiveData na arquitetura AndroidMVVM

Se você quiser obter um elemento específico de uma lista LiveData, precisará limitar sua consulta com um deslocamento.

Por padrão, limitar uma consulta não considera um deslocamento para ela; portanto, o valor de deslocamento padrão é 0.

Por exemplo, em seu Dao :

As consultas abaixo do Exemplo 1 e 2 são equivalentes, porque o valor de deslocamento padrão é 0.

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

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

Exemplo 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

Observação: Aqui estou assumindo que sua classe de modelo é Student

Isso é sobre a primeira linha; mas para retornar o número da linha x então você precisa manipular o deslocamento para ser:x-1 , pois o deslocamento é um valor baseado em 0

Exemplo 3 (mesma consulta Dao do Exemplo 2)
getStudents(1, 1); // returns the second row
getStudents(1, 4); // returns the fifth row

Se você quiser retornar mais de uma linha, precisará manipular o LIMIT valor, para retornar x linhas dos resultados e limite a consulta com x .
getStudents(2, 1); // returns the second and third rows
getStudents(3, 4); // returns the fifth, sixth, and seventh rows

Espero que isso resolva sua pergunta

Editar conforme comentários

Já tenho uma lista retornada por outra consulta @Query("SELECT * FROM students) LiveData<List<Student>> getStudents(); Portanto, o valor retornado é uma lista. Eu quero pegar o primeiro elemento da lista. Esta resposta retorna o primeiro elemento verdadeiramente, mas eu preciso passar todas as etapas (para definir este método no ViewModel class e observe-a na MainActivity para obter a lista ou qualquer elemento da lista). O que eu preciso é digitar o primeiro valor da lista enquanto eu divirto a função na classe do repositório. –

Agora você está usando a consulta abaixo
@Query("SELECT * FROM students")
LiveData<List<Student>> getStudents();

E você quer:
  1. Obtenha o primeiro ou qualquer elemento da lista. e fazê-lo de acordo com o mencionado acima
  2. Passe todas as etapas (para definir este método no ViewModel class e observe-o na MainActivity para obter a lista ou qualquer elemento da lista).

Então para fazer isso:

No Dao: :Altere sua consulta para
@Query("SELECT * FROM students LIMIT  :limit OFFSET :offset")
LiveData<List<Student>> getAllStudents(int limit, int offset);

No repositório:
public class StudentRepository {

    ...

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

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

Em atividade:
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

            }
        }
    });
}

E para testar isso:
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.

E para retornar o primeiro elemento na lista mAllStudents para digitar o nome do primeiro aluno no Log.d

Então, em sua atividade
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());
        }
    }
});

Edit é possível retornar qualquer elemento da lista sem seguir todos os passos como escrever uma função no ViewModeland observar isso no MainActivity? Minha pergunta não é seguir todos os passos.

Sim, é possível, mas o modelo acima é o modelo recomendado pelo Google, você pode retornar um List<Student> de Dao consulta em vez de LiveData<List<Student>> , mas as más notícias são:
  1. Você tem que lidar com isso em um thread de segundo plano separado; porque o LiveData faça isso de graça.
  2. Você perderá o valor do LiveData; portanto, você precisa atualizar manualmente a lista para verificar qualquer atualização, pois não poderá usar o padrão observador.

Portanto, você pode omitir o uso de ViewModel e Repository , e faça todas as coisas da atividade da seguinte forma:
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);

E a consulta para o Dao:
@Query("SELECT * FROM students LIMIT  :limit OFFSET :offset")
List<Student> getAllStudents(int limit, int offset);