仅第一次调用 LiveData onChanged 方法

Posted

技术标签:

【中文标题】仅第一次调用 LiveData onChanged 方法【英文标题】:LiveData onChanged method called only first time 【发布时间】:2018-10-02 12:17:19 【问题描述】:

我有一个简单的应用程序,它可以轮询服务以在回收站视图中显示国家/地区列表。在这里,只要国家/地区列表有任何变化,我就会使用 LiveData 更新回收站视图。麻烦的是,LiveData 的 onChanged 方法仅在第一次调用 setValue 时才被调用。但在那之后,如果数据有任何进一步的变化,onChanged 就不会被调用??

以下是我的代码以获取更多信息 -

CountryListFragment

        //Setup observer
    Observer<List<CountryModel>> myObserver = new Observer<List<CountryModel>>() 
        @Override
        public void onChanged(@Nullable List<CountryModel> countryModels) 
            mCountryList = countryModels;
            //Update recyclerview
            myAdapter.updateRecyclerView(mCountryList);
        
    ;
    //Set Observer for Viewmodel
    countryViewModel.getmCountryList().observe(this,myObserver);

CountryViewModel

公共类 CountryViewModel 扩展 androidViewModel 私有 MutableLiveData> mCountryList; 私人 MyRetrofitClient myRetrofitClient;

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


public void init()
    mCountryList = new MutableLiveData<>();
    myRetrofitClient = new MyRetrofitClient();
    **mCountryList = myRetrofitClient.getCountryList();   //This works**
    pollCountryList();


//Create polling request for every 10 secs
private void pollCountryList()
    final Handler mHandler = new Handler();

        new Thread(new Runnable() 
            @Override
            public void run() 
                for (int i=0; i<30;i++)
                    try 
                        Thread.sleep(10000);
                     catch (InterruptedException e) 
                        e.printStackTrace();
                    
                    //Call API on main thread
                    mHandler.post(new Runnable() 
                        @Override
                        public void run() 
                            **myRetrofitClient.getCountryList();  //NOT CALLING ONCHANGED??**
                        
                    );
                

            
        ).start();


public MutableLiveData<List<CountryModel>> getmCountryList() 
    return mCountryList;

MyRetrofitClient.getCountryList()

public MutableLiveData<List<CountryModel>> getCountryList()
    final MutableLiveData<List<CountryModel>> lstResult = new MutableLiveData<>();
    MockServiceInterface serviceInterface = mRetrofit.create(MockServiceInterface.class);
    Call<List<CountryModel>> countryList = serviceInterface.getCountryList();
    countryList.enqueue(new Callback<List<CountryModel>>() 
        @Override
        public void onResponse(Call<List<CountryModel>> call, Response<List<CountryModel>> response) 
            if (response.isSuccessful())
                List<CountryModel> lstResponse = response.body();
                lstResult.setValue(lstResponse);
            else 
                System.out.print(response.errorBody());
            
        
        @Override
        public void onFailure(Call<List<CountryModel>> call, Throwable t) 
            t.printStackTrace();
        
    );
    return lstResult;

谢谢!

编辑:

一些额外的观察- 当我在 CountryViewModel 中调用 MutableLiveData 实例 (mCountryList) 的 setValue 方法时,它每次都会调用 onChanged 方法。

但是在 MyRetrofitClient 的情况下它有所不同。在 MyRetrofitClient.getCountryList() 中第一次调用 setValue 时,它​​会调用 onChanged 方法。但后来就没有了。

【问题讨论】:

【参考方案1】:

抱歉,一开始我误解了问题。

您没有收到更改,因为您从未在 mCountryList 上调用过 setValue

方法 getCountryList() 正在返回新对象 MutableLiveData&lt;List&lt;CountryModel&gt;&gt; lstResult 它被调用的所有内容,没有人观察。

解决方案:

不是用getCountryList返回MutableLiveData对象,而是在onResponse()中设置mCountryList

代码

public void init()
    mCountryList = new MutableLiveData<>();
    myRetrofitClient = new MyRetrofitClient();
    myRetrofitClient.getCountryList();
    pollCountryList();


public LiveData<List<CountryModel>> getCountryListener() 
    return mCountryList;


public void getCountryList()
    MockServiceInterface serviceInterface = mRetrofit.create(MockServiceInterface.class);
    Call<List<CountryModel>> countryList = serviceInterface.getCountryList();
    countryList.enqueue(new Callback<List<CountryModel>>() 
        @Override
        public void onResponse(Call<List<CountryModel>> call, Response<List<CountryModel>> response) 
            if (response.isSuccessful())
                List<CountryModel> lstResponse = response.body();
                mCountryList.setValue(lstResponse);
            else 
                System.out.print(response.errorBody());
            
        
        @Override
        public void onFailure(Call<List<CountryModel>> call, Throwable t) 
            t.printStackTrace();
        
    );

使用getCountryListener()观察。

活动:

countryViewModel.getCountryListener().observe(this,myObserver);

【讨论】:

添加新方法 getCountryListener() 用于观察。 是的,你是对的。但是,我没有在 getCountryList 方法中分配 mCountryList,而是将 MutableLiveData lstResult 的初始化代码移到了 MyRetrofitClient 类的 init 方法中。因此在初始化期间只创建了一个 MutableLiveData 实例。这被分配给 mCountryList 并且以后每次调用它的 setValue 时,相应的 onChanged 也会被调用。谢谢!

以上是关于仅第一次调用 LiveData onChanged 方法的主要内容,如果未能解决你的问题,请参考以下文章

onChanged LiveData 未调用,RecyclerView 保持为空

Room:来自 Dao 的 LiveData 将在每次更新时触发 Observer.onChanged,即使 LiveData 值没有变化

livedata数据倒灌与粘性事件

使用LiveData处理事件

Android知识点:LiveData为啥连续postValue两次,第一次的值会丢失?

select2 onchange 事件仅有效一次