[英]How room database and viewmodel works?
我有一個students_table,並且存儲了不同級別的學生。 我想按一個級別顯示學生,而隱藏其他級別。 我選擇學生顯示如下:
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);
第一次運行時,它工作正常,轉到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;
}
StudentRepository:
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);
我希望我提供了足夠的數據。
首先,閱讀本《應用程序體系結構指南》將幫助您大致了解這些體系結構組件應如何協同工作。 經驗法則是
每個組件僅取決於其下一級的組件。
這也意味着每個組件都不應依賴於其上方的組件。 例如,存儲庫不應既不依賴於ViewModel,也不依賴於Activity。 您的代碼可以通過以下方式重構:
StudentRepository:
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中,並使視圖層盡可能簡單。
最后,活動:
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.
}
上面的代碼將顯示所有學生,因為我們在viewmodel中將默認值設置為0。 調用studentViewModel.setValue(/*any integer*/)
將列表切換到任何級別。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.