Fragment(一)简介

Fragment

Fragment最初是为了适应不同屏幕尺寸诞生的,它可以加载一个视图,然后对视图进行管理操作,类似于Activity,而Fragment本身又可作为一个视图模块,托管给Activity来管理。 这样就减轻了Activity的负担,大部分的功能可以在Fragment里实现,Activity只负责加载管理就可以了。

Fragment生命周期

Fragment与Activity类似,生命周期也有相似之处,但是多了与View和托管对象Activity有关的方法:

  • 创建:
    1.onAttach() Fragment与Activity关联时调用
    2.onCreate() Fragment初始化创建
    3.onCreateView() 建立并返回Fragment的View
    4.onViewCreated()该方法官方没有介绍,实际上会调用,View创建完成时调用
    5.onActivityCreated() 当托管该Fragment的Activity完成创建(onCreate)时调用

  • 创建完成开始运行
    1.onStart()
    2.onResume()

  • 转入后台
    1.onPause()
    2.onStop()

以上方法与Activity是一样的,Activity调用时,Fragment也会跟着调用。

  • 结束
    1.onDestroyView()与onActivityCreated()对应,Fragment视图被移除时调用
    2.onDestroy()
    3.onDetach()与onAttach对应,与Activity解除关联时调用。

  • 状态保存与恢复
    与Activity一样,非正常退出Fragment时,也会触发 onSaveInstanceState(Bundle outState)方法,将数据保存在Bundle中,恢复的时候会调用onViewRestrored(Bundle savedInstanceState)方法。在Activity中调用的方法是onRestoreInstanceState()。

Fragment使用

Fragment是API 11 才引入的,使用的时候有android.app.fragment和v4支持包两个选项。获取FragmentManager的API也不同,v4包中使用getSupportedFragmentManager,直接继承的使用getFragmentManager

静态使用Fragment

静态使用是指将Fragment当做一个空间,定义在Layout文件中。
先定义一个Fragment引用的layout文件:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/item_content"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:gravity="center"
          android:text="Item Frament">
</TextView>

然后新建Fragment,加载视图:

public class ItemFragment  extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.item,container,false);
        return v;
    }
}

到这里Fragment的部分完成了,可以把这个Fragment当做控件在XMl中直接引用,下面是Activity的layout文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <fragment
        android:id="@+id/frag_item"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.cris.miniweather.model.fragment.ItemFragment"/>
</LinearLayout>

在Activity里setContentView设置这个layout就可以了。注意fragment控件必须指定id,否则会崩溃

动态使用Fragment

和静态使用步骤类似,都需要先建立好Fragment和它对应的layout文件,不同的是在Activity中引用时,使用FragmentManager来管理Fragment。

先完成Fragment使用的layout(frag_list),这里用了Recyclerview:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/list_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

</android.support.v7.widget.RecyclerView>

Recyclerview的对应的layout文件(item.xml),一个TextView:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/item_content"
          android:layout_width="match_parent"
          android:layout_height="50dp"
          android:gravity="center"
          android:text="Item Frament">
</TextView>

然后建立Fragment(TitleListFragment.java),这里实现的是一个最简单的recyclerview

public class TitleListFragment extends android.support.v4.app.Fragment{
    private List<String> mItems;
     @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         mItems = new ArrayList<>();
         for(int i = 0; i<50; i++ ){
             String item = "Title No." + i;
             mItems.add(item);
         }
    }
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.list_title,container,false);
        RecyclerView mRecyclerView = (RecyclerView) v.findViewById(R.id.frag_list);
        RecyclerView.LayoutManager manager=new LinearLayoutManager(getActivity());
        manager.setAutoMeasureEnabled(true);
        mRecyclerView.setLayoutManager(manager);
        mRecyclerView.setAdapter(new RecycleAdapter());
        return v;
    }
    private class RecycleHolder extends RecyclerView.ViewHolder{
        private TextView mTextView;
        public RecycleHolder(View itemView) {
            super(itemView);
            mTextView = (TextView) itemView;
        }
    }
    private class RecycleAdapter extends RecyclerView.Adapter<RecycleHolder>
    {
        @Override
        public RecycleHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View TitleItemView = LayoutInflater.from(getActivity()).inflate(R.layout.item,parent,false);
            return new RecycleHolder(TitleItemView);
        }
        @Override
        public void onBindViewHolder(RecycleHolder holder, int position) {
            holder.mTextView.setText(mItems.get(position));
        }
        @Override
        public int getItemCount() {
            return mItems.size();
        }
    }
}

到这里,Fragment的部分已经完成,可以在Activity里加载它了,先设置Activity的layout文件,一个空的FrameLayout,作为Fragment的容器:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:id="@+id/frag_container"
             android:layout_width="match_parent"
             android:layout_height="match_parent">
</FrameLayout>

在Activity里加载Fragment:

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment_container);
        FragmentManager fm= getSupportFragmentManager();
        if(fm.findFragmentById(R.id.frag_container) ==null) {
            fm.beginTransaction()
                    .add(R.id.frag_container, new TitleListFragment())
                    .commit();
        }
    }

注意:
1.在Activity里是用FragmentManager来管理Fragment的,findFragmentById里的参数是Fragment容器的id,返回的是它所管理的Fragment。
2.在add方法之前,需要加一个判断,如果为null才会去添加Fragment。因为Activity非正常退出,并且被回收的时候,FragmentManager 会将它所管理的Fragment队列保存下次,Activity重新建立的时候,FragmentManager 会先回复它所保存的队列,并重建Fragment。

Fragment常用API

与Fragment相关的API主要有以下两大类

  • FragmentManager
  1. beginTransaction() 获取FragmentTransaction对象,用来操作Fragment
  1. findFragmentById(id) 获取id对应的父容器中的当前Fragment
  2. findFragmentByTag(String tag) 获取tag对应的Fragment,tag在add时添加
  3. getFragment(Bundle bundle, String key) 与putFragment对应,将一个Fragment对象放在Bundle数据中
  4. isDestroyed() 托管该Fragment的Activity执行onDestroy后,会返回true。
  5. void popBackStack() 将栈顶对象弹出。相当于back键
  6. saveFragmentInstanceState(Fragment f) 存储f的状态。
  • FragmentTransaction
  1. add(Fragment fragment, String tag); 调用第三个方法,containerViewId为0
  1. add(int containerViewId, Fragment fragment) 调用第三个方法,tag为null
  2. add(int containerViewId, Fragment fragment, String tag);添加fragment到container中
  3. addToBackStack(String name)添加Fragment到name返回栈中,默认为null
  4. attach(Fragment fragment) 在使用detach方法与UI解除关联之后重新关联
  5. commit() 提交事物
  6. detach(Fragment fragment) 从UI中解除Fragment的绑定。
  7. remove(Fragment fragment) 移除一个已经存在了的Fragment。
  8. hide(Fragment fragment) 隐藏一个存在的Fragment
  9. show(Fragment fragment) 显示一个之前隐藏的Fragment。
  10. replace(int containerViewId, Fragment fragment, String tag);替换一个已经存在了的Fragment(先remove,在add)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容