ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

android – ViewModel observer方法返回null

2019-07-05 13:27:04  阅读:412  来源: 互联网

标签: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.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);
        }
    }); 

错误是在这一行上特别抛出的(当我附加观察者时)

mReleasesViewModel.getUpcomingReleases(filter) ...

我的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 one rror(Exception e) {
                // Log.e(TAG, e.getMessage());
                MutableLiveData<List<_Release>> releases = new MutableLiveData<>();
                releases.setValue(null);
                upcomingReleasesListMap.put(filter, releases);
            }
        });
    }
}

Hashmap是我如何向片段提供数据的不可或缺的一部分.由于我现在如何在我的应用程序中维护6个片段,我需要为所有六个片段使用一个ViewModel.每个片段都有一个具有相同类型数据(对象和视图)的recyclelerview,但它们对该数据应用不同的过滤器.请查看ViewModel中的String filter参数,该参数将过滤器应用于数据.当然,我在ViewModel中维护所有6个片段.因为它们都需要同时更新(当用户完成更改平台列表等操作时)

解决方法:

您有异步代码,在实现这些方法时没有考虑这些异步代码,并且您最终得到一个null的LiveData,您可以在其上调用observe()抛出异常.您目前使用的流程:

>使用未知过滤器调用getUpcomingReleases()
>此过滤器不在地图中,因此您调用loadReleases()
> loadReleases()只为后台操作(firebase)设置一个监听器并立即返回
>你得到的行返回comingReleasesListMap.get(过滤器);这将返回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 one rror(Exception e) {
            // Log.e(TAG, e.getMessage());
            MutableLiveData<List<_Release>> releases = upcomingReleasesListMap.get(filter);
            releases.setValue(null);                
        }
    });
}

标签:android,viewmodel,android-livedata
来源: https://codeday.me/bug/20190705/1387618.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有