学习Fragment

很久以前就学过如何使用Fragment,但总感觉对它特别陌生,所以这次再一次认识Fragment,加深对Fragment的印象。

今天要弄懂的几个问题:

  1. Fragment是什么;
  2. 什么时候会用到Fragment;
  3. Fragment的生命周期;
  4. 如何静态和动态使用Fragment
  5. Fragment回退栈;
  6. Fragment事务;
  7. Fragment与Activity的通信;


以下是参考的博客:
- http://blog.youkuaiyun.com/lmj623565791/article/details/37970961
以下是参考的书籍:
- 《疯狂的Android讲义》电子工业出版社

                                                                                    

1.Fragment是什么

Fragment是Android3.0引入的新API,Fragment代表了Activity的子模块,因此可以把Fragment理解为Activity “片段”。虽然Fragment拥有自己的生命周期,但会受到其所在的Activity的生命周期控制,例如当Activity暂停时,该Activity内的所有Fragment都会暂停。也可以这样理解:Fragment是Activity的轻量级。在Activity在运行过程中,可以通过FragmentManager的add()remove()replace();方法去动态地添加、删除、替换 Fragment。一个Activity可以同时组合多个Fragment,反过来一个Fragment可以同时被多个Activity复用。


2.什么时候会用到Fragment

  • 需频繁切换界面显示的需求下;
  • 在资源有限的情况下;
  • 缓解Activity任务过重的情况下;
  • 处理在不同屏幕上的UI组件的布局问题(平板、横竖屏);
  • 将屏幕分为多个碎片;

         (如果还有,请评论补充!)


3.Fragment的生命周期

与Activity类似的是,Fragment也有:运行状态暂停状态停止状态销毁状态

onAttach():当Fragment被添加到Activity时被回调;

onCreate():创建Fragment时被回调;

onCreateView()每次创建、绘制view时被回调;

onActivityCreated():当Fragment所在的Activity被启动完成后被回调;

onStart():启动Fragment时被回调;

onResume():恢复Fragment时被回调;

onPause():暂停Fragment时被回调(可见,但不能获得焦点);

onStop():停止Fragment时被回调(不可见,失去焦点);

onDestroyView()销毁Fragment所包含的view组件时被调用;

onDestroy():销毁Fragment时被回调;

onDetach():将Fragment从Activity中删除、替换完成时被回调;


1




4.1 静态使用Fragment

静态就相当于主xml添加两个<fragment>控件,通过name属性再绑定两个java文件,并且java文件继承于Fragment,重新onCreateView(),return回各自绑定的xml文件。


代码我就不贴了,这个应该是最基础最基础的了。

4.2 动态使用Fragment

做个小demo,就是2个按钮,单击切换fragment

activity_main.xml

<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">
 

    <FrameLayout
        android:id="@+id/id_content"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/bta"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="A" />

        <Button
            android:id="@+id/btb"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="B" />
    </LinearLayout>

 </LinearLayout>

接下来是MainActivity

public class MainActivity extends ActionBarActivity implements View.OnClickListener {
    private Button bta, btb;
    private FragmentA newfragmenta;
    private FragmentB newfragmentb;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bta = (Button) findViewById(R.id.bta);
        btb = (Button) findViewById(R.id.btb);

        // 设置默认的Fragment  
        setDefaultFragment();

        //按钮事件
        bta.setOnClickListener(this);
        btb.setOnClickListener(this);
    }

    private void setDefaultFragment() {
        FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        newfragmenta = new FragmentA();
        ft.replace(R.id.id_content, newfragmenta).commit();
    }

    @Override
    public void onClick(View v) {
        FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();

        switch (v.getId()) {
            case R.id.bta:
                if (newfragmenta == null) {
                    newfragmenta = new FragmentA();
                }
                ft.replace(R.id.id_content, newfragmenta).commit();
                break;
            case R.id.btb:
                if (newfragmentb == null) {
                    newfragmentb = new FragmentB();
                }
                ft.replace(R.id.id_content, newfragmentb).commit();
                break;
        }

    }

两个xml文件 fragmenta.xml 

<?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:gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello I'm A" />
</LinearLayout>

fragmentb.xml

<?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:gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hey,I'm B " />
</LinearLayout>
两个fragment的java文件几乎一致,就只贴一个出来就行

public class FragmentA extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragmenta, container, false);
    }
}
现在我们开看看效果

其关键的就是

        FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        newfragmenta = new FragmentA();   
        ft.replace(R.id.id_content, newfragmenta).commit()//用FragmentA 替换id_content


Fragment常用的三个类:

android.app.Fragment 主要用于定义Fragment

android.app.FragmentManager 主要用于在Activity中操作Fragment

android.app.FragmentTransaction 保证一些列Fragment操作的原子性,熟悉事务这个词,一定能明白~


a、获取FragmentManage的方式:getFragmentManager() // v4中,getSupportFragmentManager


b、主要的操作都是FragmentTransaction的方法:FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务

  • transaction.add() :往Activity中添加一个Fragment;
  • transaction.remove() 从Activity中移除一个Fragment(没有添加到回退栈的情况);
  • transaction.replace():使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体;
  • transaction.hide():隐藏当前的Fragment,仅仅是设为不可见,并不会销毁;
  • transaction.show():显示之前隐藏的Fragment;
  • transatcion.commit():提交事物;

注意:常用Fragment的哥们,可能会经常遇到这样Activity状态不一致:State loss这样的错误。主要是因为:commit方法一定要在Activity.onSaveInstance()之前调用。

————————————————————————

5.Fragment回退栈

  FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.id_content, fragmentB, "B");
        ft.addToBackStack(null);//加入回退栈
       ft.commit();
在代码中添加addToBackStack(null)这一句就将回退栈里,当按回退键的时候逐层返回,直至栈空然后完全退出到桌面。

可以看demo效果图:


我来解析一下这个demo,通过点击Abutton启动fragmentB,Bbutton启动fragmentC,然后单击回退键,逐层退出栈。


MainActivity的布局文件:

<LinearLayout 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"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/id_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></FrameLayout>


</LinearLayout>
MainActivity.java文件:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.add(R.id.id_content, new FragmentA(), "A");
        ft.commit();

    }
FragmentA.java文件:

public class FragmentA extends Fragment implements View.OnClickListener {

    private Button bta;
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View viewboot = inflater.inflate(R.layout.fragmenta, container, false);
        bta = (Button) viewboot.findViewById(R.id.bta);
        bta.setOnClickListener(this);
        return viewboot;
    }

    @Override
    public void onClick(View v) {
        FragmentB fragmentB = new FragmentB();//声明fragmentB
        FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.id_content, fragmentB, "B");
        ft.addToBackStack(null);
        ft.commit();
    }
}

FragmentB.java文件:

public class FragmentB extends Fragment implements View.OnClickListener {

    private Button btb;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View viewboot = inflater.inflate(R.layout.fragmentb, container, false);

        btb = (Button) viewboot.findViewById(R.id.btb);
        btb.setOnClickListener(this);
        return viewboot;
    }

    @Override
    public void onClick(View v) {
        FragmentC fragmentc = new FragmentC();//声明fragmentC
        FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.hide(this);//将FragmnetB隐藏起来,负责会B、C重叠起来
        ft.add(R.id.id_content, fragmentc, "C");
        ft.addToBackStack(null);
        ft.commit();
    }
}

FragmentC.java文件:

public class FragmentC extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View viewboot = inflater.inflate(R.layout.fragmentc, container, false);
        return viewboot;
    }
}
3个XML文件就不贴出来了,就根据效果图来看就可以完成。

——————————————————————————————————

相关文章:

Fragment回退键addToBackStack无效的解决方法 

两个简单Fragment之间的通信







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值