为啥观察 LiveData 时不调用 onChanged()

Posted

技术标签:

【中文标题】为啥观察 LiveData 时不调用 onChanged()【英文标题】:Why is onChanged() not called when observing LiveData为什么观察 LiveData 时不调用 onChanged() 【发布时间】:2019-01-18 11:30:33 【问题描述】:

这个问题是对这个问题的跟进:How to make retrofit API call using ViewModel and LiveData

该帖子回复中突出显示的错误 1 ​​和 2 已得到修复。对于错误 3,我还没有将 API 调用移动到存储库,但是一旦代码开始正常工作,我就会这样做。

所以我正在尝试使用 Retrofit 进行 API 调用,将 MVVM 与 LiveData 和 ViewModel 结合使用。 API 调用(当前位于 ViewModel 中)正常工作,但 Activity 中的观察者没有接收到更改。

我的 ViewModel 观察者设置如下:

public class PopularGamesActivity extends AppCompatActivity 


private static final String igdbBaseUrl = "https://api-endpoint.igdb.com/";
private static final String FIELDS = "id,name,genres,cover,popularity";
private static final String ORDER = "popularity:desc";
private static final int LIMIT = 30;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_popular_games);

    PopularGamesViewModel popViewModel = ViewModelProviders.of(this).get(PopularGamesViewModel.class);
    popViewModel.getGameList().observe(this, new Observer<List<Game>>() 
        @Override
        public void onChanged(@Nullable List<Game> gameList) 
            String firstName = gameList.get(0).getName();
            Timber.d(firstName);
        

我的 ViewModel 代码如下:

public class PopularGamesViewModel extends androidViewModel 

private static final String igdbBaseUrl = "https://api-endpoint.igdb.com/";
private static final String FIELDS = "id,name,genres,cover,popularity";
private static final String ORDER = "popularity:desc";
private static final int LIMIT = 30;


public PopularGamesViewModel(@NonNull Application application) 
    super(application);



public LiveData<List<Game>> getGameList() 
    final MutableLiveData<List<Game>> gameList = new MutableLiveData<>();

    // Create the retrofit builder
    Retrofit.Builder builder = new Retrofit.Builder()
            .baseUrl(igdbBaseUrl)
            .addConverterFactory(GsonConverterFactory.create());

    // Build retrofit
    Retrofit retrofit = builder.build();

    // Create the retrofit client
    RetrofitClient client = retrofit.create(RetrofitClient.class);
    Call<List<Game>> call = client.getGame(FIELDS,
            ORDER,
            LIMIT);

    call.enqueue(new Callback<List<Game>>() 
        @Override
        public void onResponse(Call<List<Game>> call, Response<List<Game>> response) 
            Timber.d("api call sucesss");
            if (response.body() != null) 
                Timber.d("First game: " + response.body().get(0).getName());

                gameList.setValue(response.body());
            
        

        @Override
        public void onFailure(Call<List<Game>> call, Throwable t) 
            Timber.d("api call failed");
        
    );

    return gameList;

当我运行代码时,ViewModel 类中的 onResponse 将从 API 调用中输出正确的响应,因此调用正常工作。但是 PopularGamesActivity 类中的 onChanged() 永远不会被调用。有人可以阐明我做错了什么吗?谢谢!

【问题讨论】:

【参考方案1】:

好的,结果证明这是一个奇怪的 android studio 错误。我最初是在我真正的 nexus 4 设备上运行代码,并且永远不会调用 onChange。但是,在模拟设备上运行它后,它立即开始工作。现在,它也可以在我的真实设备上运行。

我不知道其背后的真正原因,但如果将来有人遇到无法调用 onChange 的问题,请尝试切换设备/模拟器。

干杯。

【讨论】:

那么,您可以在 onChange 中获得即时更新,而无需发出新请求吗?因为这也是我要找的东西【参考方案2】:

我在设备上调试代码时遇到了同样的问题。 M'n 解决方案是简单地激活设备屏幕。 屏幕保护程序是问题..

【讨论】:

欢迎来到 SO!请阅读tour和How do I write a good answer?

以上是关于为啥观察 LiveData 时不调用 onChanged()的主要内容,如果未能解决你的问题,请参考以下文章

为啥用 viewLifecycleOwner 观察到的 LiveData 在 onDestroyView 之后会得到回调?

LiveData 观察()未调用

在 xml 中设置/观察 livedata 的正确方法是啥?调用观察者方法失败

未调用 LiveData 观察者

LiveData详解

Android Room LiveData观察器未更新