Android MVVM DataBinding在Fragment onCreateView()中getAdapter()显示空指针的问题的一种解决方法
来源:互联网 发布:闲鱼恶意退款 淘宝介入 编辑:程序博客网 时间:2024/05/22 00:43
Android MVVM框架和Data Binding库已经出来很长一段时间了,但是自己最近才开始在项目中使用,很是”惭愧”。因为自己习惯了Android原来的那种所有逻辑都放在Fragment或Activity中处理的方式,所以在接触Data Binding的时候,难免会遇到一些比较奇怪的问题,例如自己这次遇见的问题:在onCreateView()中ViewPager的getAdapter()报了空指针这样的错误。因为这个问题对于我自己来说比较具有代表性,所以特意在此记录一下。
在改写为MVVM之前,原来的逻辑是不会有getAdapter()为空这样的bug的(其中getAdapter()在setViewPager函数中使用到了),如下:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {if (hotCategoryBoardBinding.hotCategoryViewPager.getAdapter() == null) { hotCategoryBoardBinding.hotCategoryViewPager.setAdapter(new HotCategoryPagerAdapter(generateLines(inflater, hotCategoryBoardBinding.hotCategoryViewPager, isFull)));}CirclePageIndicator pageIndicator = hotCategoryBoardBinding.hotCategoryIndicator; pageIndicator.setViewPager(hotCategoryBoardBinding.hotCategoryViewPager);pageIndicator.setOnPageChangeListener(this);
因为需要使用到DataBinding,主要是把setAdapter代码修改为注解绑定的方式,如下:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {hotCategoryViewModel = new HotCategoryViewModel();hotCategoryBoardBinding = HotCategoryBoardBinding.inflate(inflater, container, false); hotCategoryBoardBinding.setViewModel(hotCategoryViewModel);... //省略了部分不太重要的代码hotCategoryViewModel.setViews(generateLines(inflater, hotCategoryBoardBinding.hotCategoryViewPager, isFull));//替代了setAdapterCirclePageIndicator pageIndicator = hotCategoryBoardBinding.hotCategoryIndicator; pageIndicator.setViewPager(hotCategoryBoardBinding.hotCategoryViewPager);//当程序员运行到了这一行的时候,产生崩溃pageIndicator.setOnPageChangeListener(this);
静态函数如下:
@BindingAdapter("setHotCategoryViewPager")public static void setHotCategoryViewPager(HotCategoryViewPager hotCategoryViewPager, List<View> lists){ if(hotCategoryViewPager.getAdapter() == null) { hotCategoryViewPager.setAdapter(new HotCategoryPagerAdapter(lists)); }}
xml中的相应代码:
<com.telenav.arp.module.onebox.category.HotCategoryViewPager android:id="@+id/hotCategoryViewPager" android:layout_width="0dp" android:layout_height="fill_parent" android:layout_weight="1" auto:setHotCategoryViewPager="@{viewModel.views}"//在xml中设置adapter android:layoutDirection="locale" android:gravity="center_vertical" />
上面三个代码块基本贴出了修改之后的主干部分,但这个时候发生了崩溃,堆栈如下:
06-19 07:23:35.799 16043-16043/com.telenav.app.denali.na E/AndroidRuntime: FATAL EXCEPTION: main Process: com.telenav.app.denali.na, PID: 16043 java.lang.IllegalStateException: ViewPager does not have adapter instance. at com.viewpagerindicator.CirclePageIndicator.setViewPager(CirclePageIndicator.java:388) at com.telenav.arp.module.onebox.category.HotCategoryFragment.createPagedView(HotCategoryFragment.java:151) at com.telenav.arp.module.onebox.category.HotCategoryFragment.onCreateView(HotCategoryFragment.java:217) at android.app.Fragment.performCreateView(Fragment.java:2220) at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:973) at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1148) at android.app.BackStackRecord.run(BackStackRecord.java:793) at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1535) at android.app.FragmentManagerImpl$1.run(FragmentManager.java:482) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
这个时候我感到很困惑,对于我来说,我只是把setAdapter由直接设置改为了通过绑定(当然,注解绑定的时候setAdapter不一定像之前一样在同一个地方同样地时间点被调用),为什么会出现这个bug呢?
这个时候我加了断点,分别在三个地方添加了断点:
@Overridepublic void onResume() { super.onResume();//第一个地方,标注为1}
// page indicatorCirclePageIndicator pageIndicator = hotCategoryBoardBinding.hotCategoryIndicator; pageIndicator.setViewPager(hotCategoryBoardBinding.hotCategoryViewPager);//第二个地方,在onCreateView中,标注为2pageIndicator.setOnPageChangeListener(this);
@BindingAdapter("setHotCategoryViewPager")public static void setHotCategoryViewPager(HotCategoryViewPager hotCategoryViewPager, List<View> lists){ if(hotCategoryViewPager.getAdapter() == null) { hotCategoryViewPager.setAdapter(new HotCategoryPagerAdapter(lists));//第三个地方,真正设置adapter的地方,标注为3 }}
通过断点(其实通过崩溃能感觉出来),程序执行的顺序是2、1、3。
也就是说当我运行到pageIndicator.setViewPager
的时候,3还没有执行,所以会报出之前的错误,我曾经考虑过把pageIndicator.setViewPager
的代码放置到onResume中,但是onResume的逻辑也会在@BindingAdapter(“setHotCategoryViewPager”)之前执行,所以这里应该是需要知晓这种databinding设置adapter的方式是在何时执行的,或者怎么样能让这个设置adapter的操作提前在pageIndicator.setViewPager
之前执行。
通过查阅资料和相应的API,我发现这一行代码:hotCategoryBoardBinding.executePendingBindings();
完整代码如下:
hotCategoryViewModel.setViews(generateLines(inflater, hotCategoryBoardBinding.hotCategoryViewPager, isFull));hotCategoryBoardBinding.executePendingBindings();//同样放置在onCreateView中,但是在`pageIndicator.setViewPager`之前
这个时候再去执行,发现崩溃消失了。
那么executePendingBindings是什么意思呢:它的解释如下:
/** * Evaluates the pending bindings, updating any Views that have expressions bound to * modified variables. This <b>must</b> be run on the UI thread. */
大概的意思就是:这个操作必须在UI线程执行;评估待办的绑定,对一些绑定到已改变的变量的View进行刷新。相当于强制实时更新我们的UI。所以我在这里执行了executePendingBindings之后,相当于把setAdapter操作提前在了pageIndicator.setViewPager
之前,所以这个bug就被解决了。
因为我对MVVM的DataBinding可能理解还不够深入,所以采用了这种方式去解决我的问题,如果看到文章并且解决过相似问题的朋友有更好的解决方案,麻烦告知我一下,谢谢~
- Android MVVM DataBinding在Fragment onCreateView()中getAdapter()显示空指针的问题的一种解决方法
- Android在onCreate或者在Fragment的onCreateView中获取控件、屏幕的宽高
- 避免Fragment在切换时总是重新onCreateView的问题
- android之针对fragment多次调用onCreateView的问题
- android之针对fragment多次调用onCreateView的问题
- android之针对fragment多次调用onCreateView的问题
- android之针对fragment多次调用onCreateView的问题
- android中listview的setAdapter()和getAdapter()
- android开发—Fragment中onCreateView()和onActivityCreated()的区别
- fragment多次调用onCreateView的问题
- 关于fragment多次调用onCreateView的问题
- 解决Fragment的OnCreateView
- Fragment的 onCreateView()
- fragment的handler中getActivity空指针问题
- Android Fragment无法在headview中显示的问题
- FragmentPagerAdapter调用Fragment的空指针问题
- fragment和Thread的空指针问题
- Fragment的onCreateView方法参数
- CentOS7.0配置couchbase集群
- 异常规范
- Visual Studio 2017快捷键
- document.write
- 动态规划----各种最长序列
- Android MVVM DataBinding在Fragment onCreateView()中getAdapter()显示空指针的问题的一种解决方法
- 数组名代表第一个元素
- iOS-页面传值总结
- 简单理解Socket及TCP/IP、Http、Socket的区别
- 单应性(homography)变换的公式推导过程
- OpenCV小记(2)
- 解决linux删除文件后空间没有释放问题
- 二叉树的镜像
- 简单高效的实现Android App全局字体替换