ViewModel/LiveData/Observer 设计

huangapple 未分类评论46阅读模式
英文:

ViewModel/LiveData/Observer Design

问题

以下是翻译好的内容:

我的应用从themoviedb.org获取最受欢迎或最流行的电影。

public class MainViewModel extends AndroidViewModel {

    public LiveData<List<MovieRoom>> movies;
    private AppDatabase database;

    /*
        使用构造函数初始化UI需要填充的所有数据
     */
    public MainViewModel(@NonNull Application application) {
        super(application);

        database = AppDatabase.getInstance(this.getApplication());
        movies = database.movieDao().getAllMovies();
    }

    public void getAllMovies() {
        movies = database.movieDao().getAllMovies();
    }

    public void getPopularMovies() {
        movies = database.movieDao().getPopularMovies();
    }

    public void getTopRatedMovies() {
        movies = database.movieDao().getTopRatedMovies();
    }

    public void getFavoriteMovies() {
        movies = database.movieDao().loadFavoriteMovies(true);
    }

}

在MainActivity.java中,按钮有一个点击监听器,我已经将观察者设置如下:

Button b_pop = (Button) findViewById(R.id.button_popular);
b_pop.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        mViewModel.getPopularMovies();
    }
});
mViewModel.movies.observe(this, new Observer<List<MovieRoom>>() {
    @Override
    public void onChanged(@Nullable List<MovieRoom> movieEntries) {
        mMovieAdapter.clear();
        mMovieAdapter.setList(movieEntries);
        mMovieAdapter.notifyDataSetChanged();
    }
});

问题是,当您重新分配ViewModel的“movies”变量以获取最受欢迎或最流行的电影列表时,它不会触发onChanged()方法。最受欢迎的电影列表与最流行的电影列表相同,只是顺序不同。因此,onChanged()从未被触发,我将无法将其设置到适配器中。

我正在从零开始学习ViewModel、LiveData和观察者,所以不确定如何重新设计它以使其能够工作?

英文:

My app fetches Top Rated or Most Popular movies from themoviedb.org.

ViewModel/LiveData/Observer 设计

I'm trying to implement ViewModel with LiveData to toggle these two buttons. In MainViewModel.java, I have this:


    //private static long String TAG = MainViewModel.class.getSimpleName();
    public LiveData&lt;List&lt;MovieRoom&gt;&gt; movies;
    private AppDatabase database;


    /*
        Use constructor to initialize all data that UI needs to populate
     */
    public MainViewModel(@NonNull Application application) {
        super(application);

        // how do I know this was initialized correctly?
        database = AppDatabase.getInstance(this.getApplication());
        //database = AppDatabase.getInstance(application);
        //movies is null after calling ViewModelProvider constructor

        // what are the values in movies?
        // _movieDao = null, mDatabase = null
        movies = database.movieDao().getAllMovies();
    }


    // Loads most popular movies
    public void loadData() {
        //MainViewModel.FetchMovieTask movies = new MainViewModel.FetchMovieTask();
        //movies.execute(&quot;popular&quot;);
        // Assign to movies
    }

    public void getAllMovies() {
        movies = database.movieDao().getAllMovies();
    }

    public void getPopularMovies() {
        movies = database.movieDao().getPopularMovies();
    }

    public void getTopRatedMovies() {
        movies = database.movieDao().getTopRatedMovies();
    }

    public void getFavoriteMovies() {
        movies = database.movieDao().loadFavoriteMovies(true);
    }

}

In my MainActivity.java, the buttons have an onclick listener and I have set the observer as the following:

        b_pop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //updateMovies(&quot;popular&quot;);
                mViewModel.getPopularMovies();
            }
        });
mViewModel.movies.observe(this, new Observer&lt;List&lt;MovieRoom&gt;&gt;() {
            @Override
            public void onChanged(@Nullable List&lt;MovieRoom&gt; movieEntries) {
                //Log.d(TAG, &quot;Receiving database update from LiveData&quot;);
                // mMovieAdapter.mMovies = 0
                mMovieAdapter.clear();
                // movieEntries = 0
                // mMovieAdapter mMovies = 0
                mMovieAdapter.setList(movieEntries);
                mMovieAdapter.notifyDataSetChanged();
            }
        });

Problem is, when you reassign the ViewModel's "movies" variable with top rated or most popular list of movies, it doesn't trigger onChanged(). The Top Rated list of movies is the same list of movies as the most popular, but just in different order. So onChanged() is never triggered and I will not be able to set it to the adapter.

I'm learning ViewModel, LiveData and observer from 0 so not sure how to redesign this so that it can work?

答案1

得分: 0

将新获取的数据的值通过 LiveData 的 value 传递给 ViewModel:

public void getAllMovies() {
    movies.setValue(database.movieDao().getAllMovies().getValue());
}

同时你需要使用 MutableLiveData:

public MutableLiveData<List<MovieRoom>> movies;
英文:

Pass the value of newly fetched data to the ViewModel using value on your LiveData:

public void getAllMovies() {
        movies.setValue(database.movieDao().getAllMovies().getValue())
}

Also you need MutableLiveData

public MutableLiveData&lt;List&lt;MovieRoom&gt;&gt; movies;

huangapple
  • 本文由 发表于 2020年3月16日 02:29:06
  • 转载请务必保留本文链接:https://java.coder-hub.com/60696258.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定