come ottenere il primo o (qualsiasi) elemento da un elenco LiveData nell'architettura AndroidMVVM
Se vuoi ottenere un elemento particolare da un elenco LiveData, devi limitare la tua query con un offset.
Per impostazione predefinita, la limitazione di una query non considera un offset ad essa; quindi il valore di offset predefinito è 0.
Ad esempio, nel tuo Dao
:
Le query seguenti dell'Esempio 1 e 2 sono equivalenti, poiché il valore di offset predefinito è 0.
Esempio
@Query("SELECT * FROM students LIMIT :limit")
LiveData<List<Student>> getStudents(int limit);
// Query
getStudents(1); // returns the first row of the list
Esempio 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
Nota: Qui presumo che la tua classe modello sia Student
Si tratta della prima riga; ma per restituire il numero di riga x
quindi devi manipolare l'offset in modo che sia:x-1
, poiché l'offset è un valore in base 0
Esempio 3 (stessa query Dao dell'esempio 2)
getStudents(1, 1); // returns the second row
getStudents(1, 4); // returns the fifth row
Se vuoi restituire più di una riga, devi modificare il LIMIT
valore, quindi per restituire x
righe dai risultati, quindi limita la query con x
.
getStudents(2, 1); // returns the second and third rows
getStudents(3, 4); // returns the fifth, sixth, and seventh rows
Spero che questo risponda alla tua domanda
Modifica come da commenti
Ho già un elenco restituito da un'altra query @Query("SELECT * FROM
students)
LiveData<List<Student>> getStudents();
Quindi il valore restituito è un elenco. Voglio ottenere il primo elemento dall'elenco. Questa risposta restituisce veramente il primo elemento, ma devo passare tutti i passaggi (per definire questo metodo in ViewModel
classe e osservarlo in MainActivity
per ottenere l'elenco o qualsiasi elemento nell'elenco). Quello di cui ho bisogno è digitare il primo valore nell'elenco mentre mi diverto con la funzione nella classe repository. –
Ora stai usando la query sottostante
@Query("SELECT * FROM students")
LiveData<List<Student>> getStudents();
E tu vuoi:
- Ottieni il primo o qualsiasi elemento nell'elenco. e di farlo secondo quanto sopra indicato
- Supera tutti i passaggi (per definire questo metodo in
ViewModel
classand osservalo inMainActivity
per ottenere la lista o qualsiasi elemento della lista).
Quindi per farlo:
In Dao: :cambia la tua query in
@Query("SELECT * FROM students LIMIT :limit OFFSET :offset")
LiveData<List<Student>> getAllStudents(int limit, int offset);
Nel repository:
public class StudentRepository {
...
public LiveData<List<Student>> getAllStudents(final int limit, final int offset) {
return mDAO.getAllStudents(limit, offset);
}
}
In ViewModel:
public LiveData<List<Student>> getAllStudents(final int limit, final int offset) {
return mRepository.getAllStudents(limit, offset);
}
In attività:
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 per verificarlo:
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 per restituire il primo elemento dell'elenco mAllStudents per digitare il nome del primo studente nel Log.d
Quindi, nella tua attività
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());
}
}
});
Modifica è possibile restituire qualsiasi elemento dell'elenco senza seguire tutti i passaggi come scrivere una funzione nel ViewModel e osservarlo in MainActivity? La mia domanda è di non seguire tutti i passaggi.
Sì, è possibile, ma il modello sopra è il modello consigliato da Google. Puoi restituire un List<Student>
da Dao
query invece di LiveData<List<Student>>
, ma le cattive notizie sono:
- Devi gestirlo in un thread in background separato; perché il
LiveData
fallo gratuitamente. - Perderai il valore di
LiveData
; quindi devi aggiornare manualmente l'elenco per controllare eventuali aggiornamenti poiché non sarai in grado di utilizzare il modello di osservatore.
Quindi, puoi omettere l'utilizzo di ViewModel
e Repository
, ed esegui tutte le operazioni dell'attività come segue:
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 la domanda per il Dao:
@Query("SELECT * FROM students LIMIT :limit OFFSET :offset")
List<Student> getAllStudents(int limit, int offset);