前言
既然是关于Fragment的第一篇文章,那么我觉得有点必要先讲一下Fragment是什么。
想想开发一个由两个activity组成的列表明细应用,其中一个activity管理着记录列表界面,另一个activity管理着记录明细界面(现实中也有很多例子,例如万恶的新浪微博客户端)。单击列表中的一条记录启动一个记录明细activity实例。单击后退键销毁明细activity并返回到记录列表activity界面,接下来可以再选择一条记录。理论上行得通,但是如果需要更加复杂的用户界面呈现及跳转,这就难搞了。
可以看得出UI设计的灵活性是越来越重要。而activity自身并不具有这样的灵活性。activity视图可以在运行时切换,但控制视图的代码必须在activity中实现。因而各个activity还是要捆绑特定的用户屏幕。
不想这么搞呢?那就到Fragment表演的时候了。采用fragment而不是activity进行应用的UI管理,可绕开Android系统activity规则的限制。
fragment是一种控制器对象,activity可委派它完成一些任务。通常这些任务就是管理用户界面。受管理的用户界面可以是一整屏或者屏幕的一部分。
管理用户界面的fragment有成为UI fragment。它也有自己产生于布局文件的视图。fragment视图包含了用户可以交互的可视化UI元素。
activity视图含有可供fragment视图插入的位置。如果有多个fragment要插入,activity视图也可提供多个位置。
根据应用和用户的需求,可联合使用fragment和activity来组装或重新组装用户界面。在整个生命周期过程中,技术上来说activity的视图可以保持不变。因此不用担心会违反Android系统activity规则。
问题
那么问题来了,学Fragment哪家强(笑)。好吧,问题是这么多个fragment和activity的话,每次都要弄这么一段东西
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);
if (fragment == null) {
fragment = createFragment();
fm.beginTransaction().add(R.id.fragmentContainer, fragment)
.commit();
}
虽然也就几行,但是当你有几个这样的activity的话也是挺烦的。
哦差点忘了上面需要的布局,其实这个布局个个都差不多:activity_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
对的,就是那么一个被人用得像破鞋一样的两件套。那么怎么弄能节省点呢?弄个超类呗,于是乎就有了下面这么一个SingleFragmentActivity.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
public abstract class SingleFragmentActivity extends FragmentActivity {
protected abstract Fragment createFragment();
protected int getLayoutResId() {
return R.layout.activity_fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResId());
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);
if (fragment == null) {
fragment = createFragment();
fm.beginTransaction().add(R.id.fragmentContainer, fragment)
.commit();
}
}
}
上面的引用,如果你是只针对高版本的Android系统的话,你可以直接把.support.v4去了,然后getSupportFragmentManager()也把那个Support去掉。不过事实上Android是很万恶的,你做应用的话经常会有很多第三世界的国家的阿三们拿着那些你100块卖给陵园西那些收手机的家伙的智能手机来投诉你说上面跑不了。我去,我其实心里面很想大骂一声:“用这么破的手机还装什么软件啦丢!”,但是实际上还是要说:“抱歉我们马上会修复的。”所以兼容低版本是每一个Android程序猿都要做的事。
好了,有了上面一个类和布局文件,我们要怎么用呢?
public class TodoListActivity extends SingleFragmentActivity {
@Override
protected Fragment createFragment() {
return new TodoListFragment();
}
}
对的!2行代码!2行你买不了受骗,2行你买不了上当!有木有啊有木有!(当然啦你继续做一些东西的话代码还是会越来越多的,例如里面再implements一些回调之类的)有了它妈妈再也不用担心我敲代码了!
这两样东西是经常使用fragment的程序员的必备产品。当你新建一个项目的时候,相信我,把SingleFragmentActivity.java和activity_fragment.xml都拷进去先,绝对好用。