Как работает база данных и viewmodel? - PullRequest
0 голосов
/ 08 февраля 2019

У меня имеется student_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.Что я делаю неправильно?Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Прежде всего, прочитав это Руководство по архитектуре приложения , вы получите общее представление о том, как эти архитектурные компоненты должны работать вместе.Основное правило:

каждый компонент зависит только от компонента на один уровень ниже его.

Это также означает, что каждый компонент не должен зависеть от компонентов над ним,Например, хранилище не должно зависеть ни от ViewModels, ни от 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);
}

В приведенном выше примере хранилище выглядит так, как будто оно мало что делает, и это нормально, потому что есть толькоодин слой под ним, комната.На практике у вас могут быть другие источники данных, включая клиентов сети и кеш.Задача репозитория - абстрагировать всю логику источника данных.

ViewModel:

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*/), чтобы переключить список на любой уровень.

0 голосов
/ 08 февраля 2019

Да, вы правы, на самом деле я новичок в программировании 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);

Я надеюсь, что предоставил достаточно данных.

...