您的位置:首页 > 移动开发 > Android开发

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做处理时,通过以下方式即可:

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的形式,这种方法耦合性大,需要改进。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 框架