一、fragment简介
了解fragment基本了解这三个关键词:
求同
fragment必须依托于activity,所以生命周期直接受到宿主activity的影响,一个宿主可以管理加载多个fragment。就相当于寄生一样的概念,宿主生则寄生者生,宿主死则寄生者亡。
存异
fragment可以作为activitylayout中的一部分,fragment也能定义自己的布局,当然fragment是否需要展现给用户,都是可以自己定义的。
目的
目前接触到的项目中,fragment比起activity的使用频率更高,很多时候都采用单activity宿主,多fragment的结构。这样做的好处:1. 这样比多个activity更省内存.2. 一个activiy多个fragment能有效解耦.activity承载的逻辑可以更少更清晰,其他对应的逻辑业务可以放到相对的fragment中.3. fragment有和activity一样具备ui的处理能力,也具有和宿主activity绑定的生命周期.
二、fragment生命周期
生命周期是一个很重要的东西,了解一个类的生命周期,能很轻松的决定什么时间段该干什么活,不该干什么活,有些活能不能在这里干。只有对fragment的生命周期有所掌握,才能运用自如。
生命周期介绍
下面是来源于android官网的生命周期图:
onAttach(Context context)
onAttach调用是在activity的oncreate方法中,这里的context是activity,看源码传递的都是activity。onCreate(Bundle savedInstanceState)
这里的savedInstanceState和activity的oncreate的bundle类似,即fragment在回收之前保存的一些状态值。onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
inflater,container,savedInstancestate都是fragmentManager中传入的,inflater能够将一个布局文件xml加载为一个view,container是fragment要插入的父布局,一般来着activity的布局。savedInstancestate是上一个被回收activefragment保存的数据,可能为空。oncreateview的作用就是加载fragment的布局到activity中,当然如果你这个fragment没有任何的view,也可以返回null。onActivityCreated(Bundle savedInstanceState)
前面这4个方法都在activity的onCreate()中onStart()
当activity调用onstart的时候会通过fragmentManager中的dispatchStart分发,调用其中fragment的onstart,所以和activity一样,当fragment onstart可见不可操作。onResume()
同上dispatchResume分发调用fragment的onresume方法,fragment可见可操作。onPause()
同上dispatchPause分发调用fragment的onpause方法,fragment从RESUMED恢复到STARTED的状态,fragment可见不可操作。onStop()
同上dispatchStop分发调用fragment的onstop方法,fragment的最后状态变为ACTIVITY_CREATED,不可见且不可操作,同时如果activity在内存缺少的时候被回收,那么fragment也不能幸免。onDestroyView()
在onstop之后ondestroy之前被调用,状态回归CREATED,当状态变为CREATED之后,但还没有被宿主移除。onDestroy()
- onDetach()
分发状态,ondestroy走完就接着执行onDetach。
下一篇帖子会对生命周期做详细源码分析
activity生命周期的关系
贴一张官网的图,可以先了解。至于为什么,下一篇通过源码详细分析O_O
三、fragment使用
在使用之前需要了解fragment是怎么区分身份标识的。通过Tag和Id。fragment类中有一个mTag的成员变量和一个mFragmentId成员变量,mFragmentId是非必须指定的,默认是加载的布局layout的id,当然也可以在layout中通过android:id指定其id,而mTag是添加是给定的一个String类型的tag,可以用来区分不同的fragment。即:
- Tag mTag
- Id mFragmentId
FragmentManager提供了findFragmentById和findFragmentByTag来查找对应的唯一fragment,所以这个点需要在使用之前有所了解。使用fragment的方式一般有两种:
一、直接在布局中添加fragment
android:name属性布局需要实例化的类,android:id属性提供唯一Id,即:mFragmentId,android:tag属性唯一字符串mTag。
1、 MainActivity中的布局添加fragment的布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:name="com.example.ervinli.demo.BaseFragment"
android:id="@+id/fragment_base"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
2、fragment的需要实现onCreateView的方法加载布局
public class BaseFragment extends android.app.Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_base, container, false);
}
}
3、R.layout.fragment_base布局文件
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hello_blank_fragment"/>
</FrameLayout>
二、通过FragmentManager和FragmentTransaction动态添加替换
如果加载布局的id!=0,那么mFragmentId就是布局的id,如果调用用FragmentTransaction的重载方法add(int containerViewId, Fragment fragment, String tag) 那么这个参数tag,不为空那么就是mTag。
1、MainActivity中的布局添加布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
2、MainActivity中添加逻辑
public class MainActivity extends Activity {
private FragmentTransaction mFragmentTransaction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFragmentTransaction = getFragmentManager().beginTransaction();
BaseFragment baseFragment = new BaseFragment();
mFragmentTransaction.add(R.id.fragment_container, baseFragment);
mFragmentTransaction.commit();
}
}
3、R.layout.fragment_base布局文件
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hello_blank_fragment"/>
</FrameLayout>
同样这种方法也能添加使用fragment,相比较而言,第二种比第一种更灵活,更实用。第二种方法中用到了FragmentManager、FragmentTransaction,还有为什么第二种比第一种好些,以及其他细节将会转移到下一篇博客。