簡體   English   中英

房間數據庫和viewmodel如何工作?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM