准备写一篇长文,记录一下自己写项目过程中遇到的一个问题和解决方法。积累越多,思路越广。
Fragment
首先是Fragment,这个东西一开始不太爱用,因为那时候觉得它不是Activity,上下文用起来不够爽,之后用多了感觉其实和方便,作为页面碎片呈现数据或者画面及其好用,不会有页面跳转也不需要在AndroidManifest里声明。
Fragment有它自己的生命周期,一般对它的操作都会围绕这个生命周期进行。这个生命周期图网上有好多,我就从Google大大那里拿了一张过来。
Fragment的生命周期方法挺多的,首先来看:
onCreate()、onStart()、onResume()、onPause()、onStop()、onDestroy()
这5个方法实在是太眼熟了,没错,和Activity的生命周期方法一模一样,事实上所代表的生命周期阶段也是一模一样,这里就不仔细讲了。
紧接着到了Fragment的特有部分:
onAttach()、onCreateView()、onActivityCreated()、onDestroyView()、onDetach()
onAttach():当Fragment绑定到Activity时调用
onCreateView():当Fragment的视图创建时调用
onActivityCreated():当绑定的Activity的onCreate()方法执行完时调用
onDestroyView():当Fragment的View销毁时调用
onDetach():当Fragment与Activity解除绑定时调用
ViewPager
ViewPage也是在Android开发里比较常用的一个控件了,这个控件在使用之前需要有support-v4的jar包支持,一般创建项目时已经完成导入。
ViewPager的Adapter使用的是PagerAdapter,当其中包含的内容是Fragment时,可以使用FragmentPagerAdapter或是FragmentStatePagerAdapter。
首先来解释一下这两个Adapter的区别:
FragmentPagerAdapter
在Fragment移出视线后,保留在内存当中,当Fragment再次出现时,从内存当中获取Fragment,但同时会导致一个问题,Fragment中有数据刷新时,调用notifyDataChanged()无效,对于这一个Adapter,有这一种解决方法:
- 重载 getItem()
用来生成新的和数据无关的 Fragment
public Fragment getItem(int position) {
HomeFragment hf = new HomeFragment();
return hf;
}
- 重载instantiateItem()
先用super调用父类中的 instantiateItem() ,得到对应的 Fragment 对象,然后,将对应的数据设置给Fragment中的变量。
public Object instantiateItem(ViewGroup container, int position) {
//获取Fragment对象
HomeFragment hf = (HomeFragment) super.instantiateItem(container, position);
//获取需要更新到Fragment的新数据
Object obj= list.get(position);
//通过Fragment中的寄存器设置到Fragment的变量中
hf.setObject();
return hf;
}
- 重载 getItemPosition()
返回POSITION_NONE,触发销毁对象以及重建对象
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
FragmentStatePagerAdapter
当Fragment从视线中消失后,会将消失的Fragment从内存中销毁,当再次需要显示时,会重新创建。同样会存在notifyDataChanged()无效的情况,不过处理起来就比FragmentPagerAdapter要简单的多了:
只要完成这一步处理就ok了
- 重载 getItemPosition()
返回POSITION_NONE,触发销毁对象以及重建对象
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
初始动画效果
完成以上的代码编写,基本上一个包含若干Fragment的ViewPager就搞定了,数据也能正常显示,但是有一个问题,想要在Fragment可见的时候执行动画,这要怎样才好。
首先的思路是生命周期,onStart()走起,运行起来妥妥的。。。才怪!!
没错,在onStart()的时候执行动画效果,确实是出现了,但是滑动ViewPager会发现,仅仅是第一个Fragment的动画能看见,别的都没有,这是为啥,怎么会这样,ok,看看我们的生命周期是怎么运行的。
- 重载Fragmetn的onStart()
public void onStart() {
super.onStart();
System.out.println("当前运行的Fragment的onStart()" + getArguments().getInt("position"));
}
一进入加载:
向右滑动一次:
能够看出来,onStart()因为ViewPager的特性,使得向右滑动时第二个Fragment的onStart()并不执行,这也就直接导致了我们放在onStart()中的动画在ViewPager预加载的时候就跑完了(连见面的机会都没有/(ㄒoㄒ)/~~)
那么onStart()生命周期是不行了,要不试试onResume(),好样的,国家就需要你这样勇于探索的人才。
然而。。。
这么一试生命周期是没法玩了,我们只能去翻翻Fragment里有没有什么值得一试的方法了。
一下就找到啦(其实找了有一会o( ̄ε ̄*))
就是这个方法,看看它的介绍:
当该Fragment的UI对用户来说处于可见状态时,给系统设置一个标识。
当用户能够看见该Fragment时,会调用这个方法,并且传入参数true,了解了这些,这个方法简直太好用啦。
public void setUserVisiableHint(boolean isVisiableToUser){
//当目前Fragment确实是被用户看见
if(isVisiableToUser){
//初始化动画代码块
}
}
利用以上这个方法就能达到我们在ViewPager中的Fragment显示初始动画的目的啦,顺便还提到了Fragment和ViewPager的一些基础问题,关于这两个应该会在之后的文章里详细分析,欢迎各位一起交流学习,如果有更好的方法也跪求分享。