Android ViewModel观察者方法返回null
我得到以下错误Android ViewModel观察者方法返回null,android,viewmodel,android-livedata,Android,Viewmodel,Android Livedata,我得到以下错误 Attempt to invoke virtual method 'void android.arch.lifecycle.LiveData.observe on a null object reference 从我的主要片段中的以下代码部分 mReleasesViewModel = ViewModelProviders.of(this).get(ReleasesViewModel.class); mReleasesViewModel.getUpcomingRe
Attempt to invoke virtual method 'void android.arch.lifecycle.LiveData.observe on a null object reference
从我的主要片段中的以下代码部分
mReleasesViewModel = ViewModelProviders.of(this).get(ReleasesViewModel.class);
mReleasesViewModel.getUpcomingReleases(filter).observe(this, new Observer<List<_Release>>() {
@Override
public void onChanged(@Nullable List<_Release> releases) {
// whenever the list is changed
if (releases != null) {
mUpcomingGamesAdapter.setData(releases);
mUpcomingGamesAdapter.notifyDataSetChanged();
}
mDatabaseLoading.setVisibility(View.GONE);
}
});
我的ViewModel类:
public class ReleasesViewModel extends ViewModel {
// fragment name and list
private HashMap<String, MutableLiveData<List<_Release>>> upcomingReleasesListMap = new HashMap<>();
private ReleasesRepository releasesRepository;
private ArrayList<Integer> platforms;
private String region;
public ReleasesViewModel() {
// Shared to all fragments : User settings region & platforms
region = SharedPrefManager.read(SharedPrefManager.KEY_PREF_REGION, "North America");
Set<String> defaultPlatformsSet = new HashSet<>();
platforms = SharedPrefManager.read(SharedPrefManager.PLATFORM_IDS, defaultPlatformsSet);
}
public MutableLiveData<List<_Release>> getUpcomingReleases(String filter) {
// ReleasesRepository takes a different monthly filter
releasesRepository = new ReleasesRepository(region, filter, platforms);
if (upcomingReleasesListMap.containsKey(filter)) {
// Double check if it isn't null, just in case
if (upcomingReleasesListMap.get(filter) == null) {
// if null; try again to send a new request
loadReleases(filter);
} // else just don't do anything, the list is already in the Map
} else {
// Load it in if this filter was never added to the map [New filter and new list]
loadReleases(filter);
}
return upcomingReleasesListMap.get(filter);
}
private void loadReleases(final String filter) {
releasesRepository.addListener(new FirebaseDatabaseRepository.FirebaseDatabaseRepositoryCallback<_Release>() {
@Override
public void onSuccess(List<_Release> result) {
// sort by release date
if (platforms.size() > 1) {
// Will only sort for multiple platforms filter
Collections.sort(result);
}
MutableLiveData<List<_Release>> releases = new MutableLiveData<>();
releases.setValue(result);
upcomingReleasesListMap.put(filter, releases);
}
@Override
public void onError(Exception e) {
// Log.e(TAG, e.getMessage());
MutableLiveData<List<_Release>> releases = new MutableLiveData<>();
releases.setValue(null);
upcomingReleasesListMap.put(filter, releases);
}
});
}
}
public类ReleasesViewModel扩展了ViewModel{
//片段名称和列表
私有HashMap upcomingReleasesListMap=新HashMap();
私人释放积极释放积极释放;
私有ArrayList平台;
私有字符串区域;
公共发布视图模型(){
//共享给所有片段:用户设置区域和平台
region=SharedPrefManager.read(SharedPrefManager.KEY\u PREF\u region,“北美”);
Set defaultPlatformsSet=newhashset();
platforms=SharedPrefManager.read(SharedPrefManager.PLATFORM_id,defaultPlatformsSet);
}
公共可变LiveData getUpcomingReleases(字符串筛选器){
//ReleasesRepository采用不同的月度过滤器
releasesRepository=新的releasesRepository(地区、过滤器、平台);
if(即将发布的ReleaseSLastMap.containsKey(过滤器)){
//仔细检查它是否为空,以防万一
if(upcomingReleasesListMap.get(筛选器)==null){
//如果为null,请重试发送新请求
负荷释放(过滤器);
}//否则什么也不要做,列表已经在地图上了
}否则{
//如果从未将此筛选器添加到映射[新筛选器和新列表]中,请将其加载
负荷释放(过滤器);
}
返回upcomingReleasesListMap.get(过滤器);
}
专用void loadReleases(最终字符串过滤器){
releasesRepository.addListener(新的FirebaseDatabaseRepository.FirebaseDatabaseRepositoryCallback(){
@凌驾
成功时公开作废(列表结果){
//按发布日期排序
如果(platforms.size()>1){
//将仅针对多个平台进行排序筛选
集合。排序(结果);
}
MutableLiveData releases=新的MutableLiveData();
释放。设置值(结果);
UpComingReleaseSLastMap.put(过滤器,释放);
}
@凌驾
公共无效申报人(例外e){
//Log.e(标记,e.getMessage());
MutableLiveData releases=新的MutableLiveData();
释放.setValue(null);
UpComingReleaseSLastMap.put(过滤器,释放);
}
});
}
}
Hashmap是如何为片段提供数据的一个组成部分。因为我现在在我的应用程序中维护6个片段,所以我需要为所有6个片段使用一个ViewModel。每个片段都有一个具有相同类型数据(对象和视图)的recyclerview,但它们对该数据应用不同的过滤器。请查看ViewModel中的
字符串过滤器
参数,此参数将过滤器应用于数据。当然,我要在ViewModel中维护所有6个片段。因为它们都需要同时更新(当用户完成更改平台
列表之类的操作时)您有异步代码,在实现这些方法时没有考虑到这些代码,并且最终得到一个空的LiveData,在其上调用observe()引发异常。您当前使用的流:
- 使用未知筛选器调用getUpcomingReleases()
- 此筛选器不在映射中,因此调用loadReleases()
- loadReleases()只需为后台操作(firebase)设置一个侦听器,并立即返回
- 您可以到达返回upcomingReleasesListMap.get(filter)行;这将返回null,因为firebase侦听器很可能没有完成,并且您没有为该筛选器值在映射中添加任何内容
- 使用null LiveData并失败
public MutableLiveData<List<_Release>> getUpcomingReleases(String filter) {
...
if (upcomingReleasesListMap.get(filter) == null) {
// we don't have a mapping for this filter so create one in the map
MutableLiveData<List<_Release>> releases = new MutableLiveData<>();
upcomingReleasesListMap.put(filter, releases);
// also call this method to update the LiveData
loadReleases(filter);
}
// for now just return the empty LiveData so our ui can use it
// when the firebase listener returns we will update it
return upcomingReleasesListMap.get(filter);
}
private void loadReleases(final String filter) {
releasesRepository.addListener(new FirebaseDatabaseRepository.FirebaseDatabaseRepositoryCallback<_Release>() {
@Override
public void onSuccess(List<_Release> result) {
// sort by release date
if (platforms.size() > 1) {
// Will only sort for multiple platforms filter
Collections.sort(result);
}
// just use the previous created LiveData, this time with the data we got
MutableLiveData<List<_Release>> releases = upcomingReleasesListMap.get(filter);
releases.setValue(result);
}
@Override
public void onError(Exception e) {
// Log.e(TAG, e.getMessage());
MutableLiveData<List<_Release>> releases = upcomingReleasesListMap.get(filter);
releases.setValue(null);
}
});
}
public MutableLiveData getUpcomingReleases(字符串过滤器){
...
if(upcomingReleasesListMap.get(筛选器)==null){
//我们没有此筛选器的映射,因此请在映射中创建一个
MutableLiveData releases=新的MutableLiveData();
UpComingReleaseSLastMap.put(过滤器,释放);
//也可以调用此方法来更新LiveData
负荷释放(过滤器);
}
//现在只需返回空的LiveData,这样我们的ui就可以使用它了
//当firebase侦听器返回时,我们将更新它
返回upcomingReleasesListMap.get(过滤器);
}
专用void loadReleases(最终字符串过滤器){
releasesRepository.addListener(新的FirebaseDatabaseRepository.FirebaseDatabaseRepositoryCallback(){
@凌驾
成功时公开作废(列表结果){
//按发布日期排序
如果(platforms.size()>1){
//将仅针对多个平台进行排序筛选
集合。排序(结果);
}
//只需使用之前创建的LiveData,这次使用的是我们获得的数据
MutableLiveData releases=upcomingReleasesListMap.get(过滤器);
释放。设置值(结果);
}
@凌驾
公共无效申报人(例外e){
//Log.e(标记,e.getMessage());
MutableLiveData releases=upcomingReleasesListMap.get(过滤器);
释放.setValue(null);
}
});
}
你就是mvp。
public MutableLiveData<List<_Release>> getUpcomingReleases(String filter) {
...
if (upcomingReleasesListMap.get(filter) == null) {
// we don't have a mapping for this filter so create one in the map
MutableLiveData<List<_Release>> releases = new MutableLiveData<>();
upcomingReleasesListMap.put(filter, releases);
// also call this method to update the LiveData
loadReleases(filter);
}
// for now just return the empty LiveData so our ui can use it
// when the firebase listener returns we will update it
return upcomingReleasesListMap.get(filter);
}
private void loadReleases(final String filter) {
releasesRepository.addListener(new FirebaseDatabaseRepository.FirebaseDatabaseRepositoryCallback<_Release>() {
@Override
public void onSuccess(List<_Release> result) {
// sort by release date
if (platforms.size() > 1) {
// Will only sort for multiple platforms filter
Collections.sort(result);
}
// just use the previous created LiveData, this time with the data we got
MutableLiveData<List<_Release>> releases = upcomingReleasesListMap.get(filter);
releases.setValue(result);
}
@Override
public void onError(Exception e) {
// Log.e(TAG, e.getMessage());
MutableLiveData<List<_Release>> releases = upcomingReleasesListMap.get(filter);
releases.setValue(null);
}
});
}