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 noViewModel
class e observe-a naMainActivity
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:
- Obtenha o primeiro ou qualquer elemento da lista. e fazê-lo de acordo com o mencionado acima
- Passe todas as etapas (para definir este método no
ViewModel
class e observe-o naMainActivity
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:- Você tem que lidar com isso em um thread de segundo plano separado; porque o
LiveData
faça isso de graça. - 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);