hur man får det första eller (vilket som helst) element från en LiveData List i AndroidMVVM-arkitektur
Om du vill hämta ett visst element från en LiveData-lista måste du begränsa din fråga med en offset.
Som standard betraktar begränsningen av en fråga inte som en förskjutning till den; så standardvärdet för offset är 0.
Till exempel i din Dao
:
Frågorna nedan i exempel 1 och 2 är likvärdiga, eftersom standardvärdet för offset är 0.
Exempel
@Query("SELECT * FROM students LIMIT :limit")
LiveData<List<Student>> getStudents(int limit);
// Query
getStudents(1); // returns the first row of the list
Exempel 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
Obs! Här antar jag att din modellklass är Student
Det här handlar om den första raden; men för att returnera radnummer x
då måste du manipulera offseten så att den blir:x-1
, eftersom offset är 0-baserat värde
Exempel 3 (Samma Dao-fråga som exempel 2)
getStudents(1, 1); // returns the second row
getStudents(1, 4); // returns the fifth row
Om du vill returnera mer än en rad, måste du manipulera LIMIT
värde, så att returnera x
rader från resultaten och begränsa sedan frågan med x
.
getStudents(2, 1); // returns the second and third rows
getStudents(3, 4); // returns the fifth, sixth, and seventh rows
Hoppas detta löser din fråga
Redigera enligt kommentarer
Jag har redan en lista som returneras av en annan fråga
@Query("SELECT * FROM
students)
LiveData<List<Student>> getStudents();
Så det returnerade värdet är en lista. Jag vill hämta det första elementet från listan. Det här svaret returnerar det första elementet, men jag måste klara alla stegen (för att definiera denna metod iViewModel
klass och observera den iMainActivity
för att få listan eller något element i listan). Vad jag behöver är att skriva det första värdet i listan medan jag roar funktionen i förvarsklassen. –
Nu använder du nedanstående fråga
@Query("SELECT * FROM students")
LiveData<List<Student>> getStudents();
Och du vill:
- Hämta det första eller något annat element i listan. och att göra det enligt vad som nämns ovan
- Godkänn alla steg (för att definiera denna metod i
ViewModel
). klass och observera det iMainActivity
för att få listan eller något element i listan).
Så för att göra det:
I Dao: :Ändra din fråga till
@Query("SELECT * FROM students LIMIT :limit OFFSET :offset")
LiveData<List<Student>> getAllStudents(int limit, int offset);
I arkivet:
public class StudentRepository {
...
public LiveData<List<Student>> getAllStudents(final int limit, final int offset) {
return mDAO.getAllStudents(limit, offset);
}
}
I ViewModel:
public LiveData<List<Student>> getAllStudents(final int limit, final int offset) {
return mRepository.getAllStudents(limit, offset);
}
I aktivitet:
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
}
}
});
}
Och för att testa det:
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.
Och för att returnera det första elementet i mAllStudents-listan för att skriva in det första elevnamnet i Log.d
Så, i din aktivitet
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());
}
}
});
Redigera är det möjligt att returnera valfritt element i listan utan att följa alla steg som att skriva en funktion i ViewModeland observera det i MainActivity? Min fråga är att inte följa alla stegen.
Ja det är möjligt, men ovanstående modell är den rekommenderade modellen av Google. Du kan returnera en List<Student>
från Dao
fråga istället för LiveData<List<Student>>
, men de dåliga nyheterna är:
- Du måste hantera det i en separat bakgrundstråd; eftersom
LiveData
gör det gratis. - Du kommer att förlora värdet på
LiveData
; så du måste uppdatera listan manuellt för att kontrollera eventuella uppdateringar eftersom du inte kommer att kunna använda observatörsmönstret.
Så du kan utelämna ViewModel
och Repository
, och gör alla saker från aktiviteten enligt följande:
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);
Och frågan om Dao:
@Query("SELECT * FROM students LIMIT :limit OFFSET :offset")
List<Student> getAllStudents(int limit, int offset);