房间数据库和视图模型如何工作?
How room database and viewmodel works?
我有一个students_table,存储了不同级别的学生。我想按一个级别显示学生并隐藏其他级别。
我select学生这样显示:
if (id == R.id.beginners) {
stLvl = 0;
}else if (id == R.id.intermediate) {
stLvl = 1;
}else if (id == R.id.advanced) {
stLvl = 2;
}else if (id == R.id.high_level) {
stLvl = 3;
}
showStud();
这里是showStud();
public void showStud() {
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
final StudentAdapter adapter = new StudentAdapter();
recyclerView.setAdapter(adapter);
setStLvl(stLvl);
if (stLvl == 0) {
studentViewModel = ViewModelProviders.of(this).get(StudentViewModel.class);
studentViewModel.getAllStudents().observe(this, new Observer<List<Student>>() {
@Override
public void onChanged(@Nullable List<Student> students) {
// update RecyclerView
adapter.submitList(students);
}
});
}else {
studentViewModel = ViewModelProviders.of(this).get(StudentViewModel.class);
studentViewModel.getStudentsByLevel().observe(this, new Observer<List<Student>>() {
@Override
public void onChanged(@Nullable List<Student> students) {
// update RecyclerView
adapter.submitList(students);
}
});
}
}
第一次当代码 运行 工作完美时,无论 stLvl 的值如何,但是当我更改它的值时,它的值没有显示我想要的,或者根本没有显示。
我认为问题出在这一行:
studentViewModel = ViewModelProviders.of(this).get(StudentViewModel.class);
第一次 运行s,它工作正常,去 StudentViewModel.class 做应该做的,但第二次只是跳到下一行代码,没有去 StudentViewModel.class。
我究竟做错了什么?提前致谢!
是的,你是对的,事实上我是 android 编程的初学者。这是 StudentViewModel:
private StudentRepository repository;
private LiveData<List<Student>> allStudents;
private LiveData<List<Student>> studentsByLevel;
public StudentViewModel(@NonNull Application application) {
super(application);
repository = new StudentRepository(application);
int stLevel = 0;
studentsByLevel = repository.getStudentsByLevel(stLevel);
allStudents = repository.getAllStudents();
}
.
.
.
public LiveData<List<Student>> getAllStudents() {
return allStudents;
}
public LiveData<List<Student>> getStudentsByLevel() {
return studentsByLevel;
}
学生资料库:
private StudentDao studentDao;
private LiveData<List<Student>> allStudents;
private LiveData<List<Student>> studentsByLevel;
public int stLevel;
public void setStLvl() {
MainActivity mainActivity = new MainActivity();
stLevel = mainActivity.getStLvl();
}
public StudentRepository(Application application) {
AppDatabase database = AppDatabase.getInstance(application);
studentDao = database.studentDao();
setStLvl();
studentsByLevel = studentDao.getStudentsByLevel(stLevel);
allStudents = studentDao.getAllStudents();
}
.
.
.
public LiveData<List<Student>> getAllStudents() {
return allStudents;
}
public LiveData<List<Student>> getStudentsByLevel(int stLevel) {
return studentsByLevel;
}
在 StudentDao 中我有:
@Query("SELECT * FROM student_table WHERE level = :level")
LiveData<List<Student>> getStudentsByLevel(int level);
希望我提供了足够的数据。
首先,阅读本文 Guide to app architecture 将帮助您大致了解这些体系结构组件应如何协同工作。经验法则是,
each component depends only on the component one level below it.
这也意味着每个组件不应该依赖于它上面的组件。例如,存储库不应依赖于 ViewModel 或 Activity。您的代码可以这样重构:
学生资料库:
private StudentDao studentDao;
// public int stLevel;
// public void setStLvl() { // Do not read view components. Do not store their states.
// MainActivity mainActivity = new MainActivity();
// stLevel = mainActivity.getStLvl();
// }
public StudentRepository(Application application) {
AppDatabase database = AppDatabase.getInstance(application);
studentDao = database.studentDao();
// setStLvl();
}
.
.
.
public LiveData<List<Student>> getAllStudents() {
return studentDao.getAllStudents();
}
public LiveData<List<Student>> getStudentsByLevel(int stLevel) {
return studentDao.getStudentsByLevel(stLevel);
}
在上面的示例中,存储库看起来并没有做太多事情,这很正常,因为它下面只有一层,Room。在实际实践中,您可以拥有其他数据源,包括网络客户端和缓存。存储库的工作是抽象所有数据源逻辑。
视图模型:
private MutableLiveData<Integer> studentLevel; // This will store the student level
private LiveData<List<Student>> studentsByLevel; // This will store the list of students
public StudentViewModel(@NonNull Application application) {
super(application);
repository = new StudentRepository(application);
studentLevel = new MutableLiveData<>();
// Place your logic inside the ViewModel
// Change in studentLevel will be reflected to studentsByLevel
studentsByLevel = Transformations.switchMap(studentLevel, lvl -> {
if (studentLevel == 0) {
return repository.getAllStudents();
} else {
repository.getStudentsByLevel(stLevel);
}
});
studentLevel.setValue(0) // Set initial student level.
}
.
.
.
public void setStudentLevel(int level) { // Change studentLevel anytime.
return studentLevel.setValue(level);
}
public LiveData<List<Student>> getStudentList() {
return studentsByLevel;
}
我不是 LiveData
的粉丝,但我会这样做。将所有逻辑保留在 ViewModel 中,并使视图层尽可能简单。
最后,Activity:
private StudentViewModel studentViewModel
protected void onCreate(Bundle savedInstanceState) {
...
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
final StudentAdapter adapter = new StudentAdapter();
recyclerView.setAdapter(adapter);
studentViewModel = ViewModelProviders.of(this).get(StudentViewModel.class);
studentViewModel.observe(this, students -> {
adapter.submitList(students);
});
// studentViewModel.setValue(1) // call this function anywhere you like.
}
以上代码将显示所有学生,因为我们在视图模型中将默认值设置为 0。调用 studentViewModel.setValue(/*any integer*/)
将列表切换到任意级别。
我有一个students_table,存储了不同级别的学生。我想按一个级别显示学生并隐藏其他级别。 我select学生这样显示:
if (id == R.id.beginners) {
stLvl = 0;
}else if (id == R.id.intermediate) {
stLvl = 1;
}else if (id == R.id.advanced) {
stLvl = 2;
}else if (id == R.id.high_level) {
stLvl = 3;
}
showStud();
这里是showStud();
public void showStud() {
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
final StudentAdapter adapter = new StudentAdapter();
recyclerView.setAdapter(adapter);
setStLvl(stLvl);
if (stLvl == 0) {
studentViewModel = ViewModelProviders.of(this).get(StudentViewModel.class);
studentViewModel.getAllStudents().observe(this, new Observer<List<Student>>() {
@Override
public void onChanged(@Nullable List<Student> students) {
// update RecyclerView
adapter.submitList(students);
}
});
}else {
studentViewModel = ViewModelProviders.of(this).get(StudentViewModel.class);
studentViewModel.getStudentsByLevel().observe(this, new Observer<List<Student>>() {
@Override
public void onChanged(@Nullable List<Student> students) {
// update RecyclerView
adapter.submitList(students);
}
});
}
}
第一次当代码 运行 工作完美时,无论 stLvl 的值如何,但是当我更改它的值时,它的值没有显示我想要的,或者根本没有显示。 我认为问题出在这一行:
studentViewModel = ViewModelProviders.of(this).get(StudentViewModel.class);
第一次 运行s,它工作正常,去 StudentViewModel.class 做应该做的,但第二次只是跳到下一行代码,没有去 StudentViewModel.class。 我究竟做错了什么?提前致谢!
是的,你是对的,事实上我是 android 编程的初学者。这是 StudentViewModel:
private StudentRepository repository;
private LiveData<List<Student>> allStudents;
private LiveData<List<Student>> studentsByLevel;
public StudentViewModel(@NonNull Application application) {
super(application);
repository = new StudentRepository(application);
int stLevel = 0;
studentsByLevel = repository.getStudentsByLevel(stLevel);
allStudents = repository.getAllStudents();
}
.
.
.
public LiveData<List<Student>> getAllStudents() {
return allStudents;
}
public LiveData<List<Student>> getStudentsByLevel() {
return studentsByLevel;
}
学生资料库:
private StudentDao studentDao;
private LiveData<List<Student>> allStudents;
private LiveData<List<Student>> studentsByLevel;
public int stLevel;
public void setStLvl() {
MainActivity mainActivity = new MainActivity();
stLevel = mainActivity.getStLvl();
}
public StudentRepository(Application application) {
AppDatabase database = AppDatabase.getInstance(application);
studentDao = database.studentDao();
setStLvl();
studentsByLevel = studentDao.getStudentsByLevel(stLevel);
allStudents = studentDao.getAllStudents();
}
.
.
.
public LiveData<List<Student>> getAllStudents() {
return allStudents;
}
public LiveData<List<Student>> getStudentsByLevel(int stLevel) {
return studentsByLevel;
}
在 StudentDao 中我有:
@Query("SELECT * FROM student_table WHERE level = :level")
LiveData<List<Student>> getStudentsByLevel(int level);
希望我提供了足够的数据。
首先,阅读本文 Guide to app architecture 将帮助您大致了解这些体系结构组件应如何协同工作。经验法则是,
each component depends only on the component one level below it.
这也意味着每个组件不应该依赖于它上面的组件。例如,存储库不应依赖于 ViewModel 或 Activity。您的代码可以这样重构:
学生资料库:
private StudentDao studentDao;
// public int stLevel;
// public void setStLvl() { // Do not read view components. Do not store their states.
// MainActivity mainActivity = new MainActivity();
// stLevel = mainActivity.getStLvl();
// }
public StudentRepository(Application application) {
AppDatabase database = AppDatabase.getInstance(application);
studentDao = database.studentDao();
// setStLvl();
}
.
.
.
public LiveData<List<Student>> getAllStudents() {
return studentDao.getAllStudents();
}
public LiveData<List<Student>> getStudentsByLevel(int stLevel) {
return studentDao.getStudentsByLevel(stLevel);
}
在上面的示例中,存储库看起来并没有做太多事情,这很正常,因为它下面只有一层,Room。在实际实践中,您可以拥有其他数据源,包括网络客户端和缓存。存储库的工作是抽象所有数据源逻辑。
视图模型:
private MutableLiveData<Integer> studentLevel; // This will store the student level
private LiveData<List<Student>> studentsByLevel; // This will store the list of students
public StudentViewModel(@NonNull Application application) {
super(application);
repository = new StudentRepository(application);
studentLevel = new MutableLiveData<>();
// Place your logic inside the ViewModel
// Change in studentLevel will be reflected to studentsByLevel
studentsByLevel = Transformations.switchMap(studentLevel, lvl -> {
if (studentLevel == 0) {
return repository.getAllStudents();
} else {
repository.getStudentsByLevel(stLevel);
}
});
studentLevel.setValue(0) // Set initial student level.
}
.
.
.
public void setStudentLevel(int level) { // Change studentLevel anytime.
return studentLevel.setValue(level);
}
public LiveData<List<Student>> getStudentList() {
return studentsByLevel;
}
我不是 LiveData
的粉丝,但我会这样做。将所有逻辑保留在 ViewModel 中,并使视图层尽可能简单。
最后,Activity:
private StudentViewModel studentViewModel
protected void onCreate(Bundle savedInstanceState) {
...
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
final StudentAdapter adapter = new StudentAdapter();
recyclerView.setAdapter(adapter);
studentViewModel = ViewModelProviders.of(this).get(StudentViewModel.class);
studentViewModel.observe(this, students -> {
adapter.submitList(students);
});
// studentViewModel.setValue(1) // call this function anywhere you like.
}
以上代码将显示所有学生,因为我们在视图模型中将默认值设置为 0。调用 studentViewModel.setValue(/*any integer*/)
将列表切换到任意级别。