android笔记之首页框架搭建
2016-06-20 01:31
441 查看
首页采用viewpage+fragment实现,底部tab实现活动,消息,动态和个人页面的分类展示,viewpage不可以滑动。这里涉及到以下技术点:
1. pageadapter的选择,android提供了两种显示fragment的pageadapter,fragmentpageadapter和FragmentStatePagerAdapter,它们的区别如下,fragmentpageadapter主要用于缓存数据,一般用于静态数据的page,FragmentStatePagerAdapter主要用于实时刷新数据,一般用于动态数据的page。由于fragment会缓存页面,所以对于内存要求严格或者fragment保存的数据较多占用内存较大的情况下,应当考虑使用fragmentstatepageadapter,其实总的来说就是时间和空间的选择,fragmentpageadapter是通过空间换时间来提高性能,而fragmentstatepageadapter是通过时间换空间来降低内存消耗。因为我们这里fragment的数量并不多,只有4个,所以就使用了fragmentpageadapter
2. viewpage不可滚动,需要在viewpage的onInterceptTouchEvent()和onTouchEvent()中返回false,以保证viewpage不会拦截其子控件的事件。
遇到的坑:
1. 最初的做法是使用fragmentpageadapter缓存fragments,然后根据选择的tab来显示相应的fragmet,这里遇到一个问题就是内存重启后,tab和fragmentpageadapter里面缓存的fragment对应出错,fragmentpageadapter里面在内存重启后并没有如同view一样自动保存fragment的状态,这点是自己的理解错误。
2. fragment的懒加载实现,由于viewpage的预加载机制会带来一定的性能损失和流量消耗,所以我们控制fragment在可见状态下才加载数据,这样做的目的是优化,按需加载。一般是通过重写setUserVisibleHint()来实现。
在活动fragment中使用了viewpage+fragment来完成产品的业务需求。这里就涉及到了fragment的嵌套,所以需要注意getFragmentManager()和getChildFragmentManager()的使用。另外系统自动为我们保存了activity或者fragment内的fragment,当我们需要对fragment做处理时,通过以下方式即可:
viewpage在使用fragmentpageadapter时会遇到一个使用notifyDatasetChanged()刷新页面无效的问题,这个在网络上普遍存在,也有相应的解决办法。我使用的方法如下:
继承pageadapter并重写getItemPosition()方法,为什么要重写该方法呢?因为只有当getItemPosition()的返回值为POSITION_NONE的时候,viewpage才会调用getItem()方法,这样只要我们在getItem()方法中刷新fragment就可以正常刷新数据和UI了。这种方法有些暴力,因为fragment的创建代价还是较大的,通过重写instantiateItem()方法,可以复用已有的fragment,目前app没有采用这种方式,后续可以考虑使用该方式优化。所以一种更加优雅的方式为:
我们知道fragment与activity通信一般使用接口的形式,比如让activity实现fragment中定义的某个接口,然后当fragment想要发送消息时回调该接口即可。然而当要实现activity给fragment发送消息时其实也可以采用接口的形式,让fragment实现activity中定义的某个接口,当activity想要给fragment发送消息时,回调该接口。目前app中采用直接获取fragment对象并调用相应method的形式,这种方法耦合性大,需要改进。
1. pageadapter的选择,android提供了两种显示fragment的pageadapter,fragmentpageadapter和FragmentStatePagerAdapter,它们的区别如下,fragmentpageadapter主要用于缓存数据,一般用于静态数据的page,FragmentStatePagerAdapter主要用于实时刷新数据,一般用于动态数据的page。由于fragment会缓存页面,所以对于内存要求严格或者fragment保存的数据较多占用内存较大的情况下,应当考虑使用fragmentstatepageadapter,其实总的来说就是时间和空间的选择,fragmentpageadapter是通过空间换时间来提高性能,而fragmentstatepageadapter是通过时间换空间来降低内存消耗。因为我们这里fragment的数量并不多,只有4个,所以就使用了fragmentpageadapter
2. viewpage不可滚动,需要在viewpage的onInterceptTouchEvent()和onTouchEvent()中返回false,以保证viewpage不会拦截其子控件的事件。
遇到的坑:
1. 最初的做法是使用fragmentpageadapter缓存fragments,然后根据选择的tab来显示相应的fragmet,这里遇到一个问题就是内存重启后,tab和fragmentpageadapter里面缓存的fragment对应出错,fragmentpageadapter里面在内存重启后并没有如同view一样自动保存fragment的状态,这点是自己的理解错误。
2. fragment的懒加载实现,由于viewpage的预加载机制会带来一定的性能损失和流量消耗,所以我们控制fragment在可见状态下才加载数据,这样做的目的是优化,按需加载。一般是通过重写setUserVisibleHint()来实现。
在活动fragment中使用了viewpage+fragment来完成产品的业务需求。这里就涉及到了fragment的嵌套,所以需要注意getFragmentManager()和getChildFragmentManager()的使用。另外系统自动为我们保存了activity或者fragment内的fragment,当我们需要对fragment做处理时,通过以下方式即可:
try { List<Fragment> fragments = getChildFragmentManager().getFragments(); for (int i = 0; i < fragments.size(); i++) { if (fragments.get(i) instanceof ActivityFragment) { ActivityFragment fragmentActivity = (ActivityFragment) fragments.get(i); } } } catch (Exception e) { }
viewpage在使用fragmentpageadapter时会遇到一个使用notifyDatasetChanged()刷新页面无效的问题,这个在网络上普遍存在,也有相应的解决办法。我使用的方法如下:
@Override public int getCount() { return fragments == null ? 0 : fragments.size(); } @Override public Fragment getItem(int position) { return fragments.get(position); } @Override public int getItemPosition(Object object) { return POSITION_NONE; } public void setSource(ArrayList<ActivityFragment> fragments) { if (this.fragments != null && !this.fragments.isEmpty()) { FragmentTransaction ft = fm.beginTransaction(); for (ActivityFragment f : this.fragments) { ft.remove(f); } ft.commit(); fm.executePendingTransactions(); } this.fragments = fragments; notifyDataSetChanged(); }
继承pageadapter并重写getItemPosition()方法,为什么要重写该方法呢?因为只有当getItemPosition()的返回值为POSITION_NONE的时候,viewpage才会调用getItem()方法,这样只要我们在getItem()方法中刷新fragment就可以正常刷新数据和UI了。这种方法有些暴力,因为fragment的创建代价还是较大的,通过重写instantiateItem()方法,可以复用已有的fragment,目前app没有采用这种方式,后续可以考虑使用该方式优化。所以一种更加优雅的方式为:
@Override public Object instantiateItem(ViewGroup container, int position) { ActivityFragment fragment = (ActivityFragment) super.instantiateItem(container, position); Model data = datas.get(position); fragment.setData(data); return fragment; }
我们知道fragment与activity通信一般使用接口的形式,比如让activity实现fragment中定义的某个接口,然后当fragment想要发送消息时回调该接口即可。然而当要实现activity给fragment发送消息时其实也可以采用接口的形式,让fragment实现activity中定义的某个接口,当activity想要给fragment发送消息时,回调该接口。目前app中采用直接获取fragment对象并调用相应method的形式,这种方法耦合性大,需要改进。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories