如何从Android MVVM体系结构的LiveData列表中获取第一个或(任何)元素? [英] how to get the first or (any) element from a LiveData List in Android MVVM architecture?
问题描述
我使用MVVM架构构建了一个带有Repository作为ViewModel和Room数据库之间中介的Android应用程序.在其中一个函数中,我从存储库类中的表中检索对象列表,以便可以从ViewModel类中调用它.
I used MVVM architecture to build an Android application with a Repository as a mediation between the ViewModel and Room database. In one of the functions, I retrieve a list of objects from a table in the repository class so that I can call it from the ViewModel class.
如何从存储库类中检索列表中的第一个元素,而不是在任何一项活动中观察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(名字",mAllStudent.get(0)); //我想在日志中输入学生姓名,而无需在其中添加函数 viewModel并在任何活动中观察到
Log.d("First_Name",mAllStudent.get(0)); // I want to type the student name in the Log without adding a function in the viewModel and observe that in any Activity
return mAllStudents;
}
}
推荐答案
如何从Android中的LiveData列表中获取第一个或(任何)元素 MVVM体系结构
how to get the first or (any) element from a LiveData List in Android MVVM architecture
如果要从LiveData列表中获取特定元素,则需要使用偏移量限制查询.
If you want to get a particular element from a LiveData list, then you need to limit your query with an offset.
默认情况下,限制查询不会考虑该查询的偏移量;因此默认偏移值为0.
By default limiting a query doesn't consider an offset to it; so the default offset value is 0.
例如,在您的Dao
中:
例1和示例2的以下查询2是等效的,因为默认偏移值为0.
The below queries of Example 1 & 2 are equivalent, because the default offset value is 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
Note: Here I am assuming your model class is Student
这是关于第一行;但要返回行号 x
,则需要将偏移量设置为: x-1
,因为偏移量是基于0的值
This is about the first row; but to return row number x
then you need to manipulate the offset to be: x-1
, as the offset is 0-based value
示例3(与示例2相同的Dao查询)
getStudents(1, 1); // returns the second row
getStudents(1, 4); // returns the fifth row
如果要返回多个行,则需要操纵LIMIT
值,因此要从结果中返回 x
行,然后将查询限制为 x
.
If you want to return more than one row, then you need to manipulate the LIMIT
value, so to return x
rows from the results, then limit the query with 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
中以获取列表或列表中的任何元素
列表).我需要的是在输入的同时键入列表中的第一个值
使用存储库类中的函数. –
I already have a list returned by another query @Query("SELECT * FROM
students)
LiveData<List<Student>> getStudents();
So the returned value
is a list. I want to get the first element from the list.
This answer returns the first element truly, but I need to pass all
the steps (to define this method in the ViewModel
class and observe it
in the MainActivity
in order to get the list or any element in the
list). What I need is to type the first value in the list while I am
using the function in the repository class. –
现在您正在使用以下查询
Now you are using below query
@Query("SELECT * FROM students")
LiveData<List<Student>> getStudents();
您要:
- 获取列表中的第一个或任何元素.并按照 上面提到的
- 通过所有步骤(以在
ViewModel
类中定义此方法 并在MainActivity
中观察它以获取列表或任何其他内容 列表中的元素).
- Get the first or any element in the list. and to do so according to what is mentioned above
- Pass all the steps (to define this method in the
ViewModel
class and observe it in theMainActivity
in order to get the list or any element in the list).
要这样做:
在道中:将查询更改为
@Query("SELECT * FROM students LIMIT :limit OFFSET :offset")
LiveData<List<Student>> getAllStudents(int limit, int offset);
在存储库中:
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中观察到?我的问题不是全部 步骤.
Edit is it possible to return any element of the list without following all the steps such as writing a function in the ViewModel and observe that in the MainActivity? My question is not to follow all the steps.
是可以的,但是上面的模型是Google推荐的模型,您可以从Dao
查询而不是LiveData<List<Student>>
返回List<Student>
,但是坏消息是:
Yes it's possible, but the above model is the recommended model by Google, You can return a List<Student>
from Dao
query instead of LiveData<List<Student>>
, but the bad news are:
- 您必须在单独的后台线程中处理该问题;因为
LiveData
免费这样做. - 您将失去
LiveData
的价值;所以你必须手动 刷新列表以检查是否有更新,因为您将无法使用观察者模式.
- You have to handle that in a separate background thread; because the
LiveData
do that for free. - You will lose the value of the
LiveData
; so you have to manually refresh the list to check any update as you won't be able to use the observer pattern.
因此,您可以省略ViewModel
和Repository
,并按照以下步骤执行活动中的所有工作:
So, you can omit using ViewModel
and Repository
, and do all the stuff from the activity as follows:
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);
然后查询Dao:
@Query("SELECT * FROM students LIMIT :limit OFFSET :offset")
List<Student> getAllStudents(int limit, int offset);
这篇关于如何从Android MVVM体系结构的LiveData列表中获取第一个或(任何)元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!