Fragment 1

Fragment 简介

Google最初引入Fragment主要是为了给大屏幕(如平板电脑)上更加动态和灵活的 UI 设计提供支持。作为 Activity 界面的一部分,Fragment 的存在必须依附于 Activity,并且与 Activity 一样,拥有自己的生命周期,同时处理用户的交互动作。同一个 Activity 可以有一个或多个 Fragment 作为界面内容,并且可以动态添加、删除 Fragment,灵活控制 UI 内容,也可以用来解决部分屏幕适配问题。

我们可以在多个Activity中重复使用某个片段,并且可以按我们的需求把不同的片段组合在一个界面中,好处显而易见,减少工作量提高了代码的可重用性。

Fragment基本用法

布局静态嵌入

首先同Activity一样先给Fragment创建一个布局文件,接着新建一个 LeftFragment 类,继承自 Fragment。

public class LeftFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.left_fragment, container, false);
        return view;
} }

这里仅仅是重写了 Fragment 的 onCreateView()方法,然后在这个方法中通过 LayoutInflater 的 inflate()方法将刚才定义的 left_fragment 布局动态加载进来

接下来修改 activity_main.xml 中的代码,在Activity的布局文件中添加该Fragment。需要通过 android:name 属性来显式指明要添加的碎片类名。

<fragment
    android:id="@+id/right_fragment"
    android:name="com.example.fragmenttest.RightFragment"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1" />

代码动态嵌入

动态添加碎片主要分为 5 步。
1. 创建待添加的碎片实例。
2. 获取到 FragmentManager,在活动中可以直接调用 getFragmentManager()方法得到。
3. 开启一个事务,通过调用 beginTransaction()方法开启。
4. 向容器内加入碎片,一般使用 replace()方法实现,需要传入容器的 id 和待添加的碎
片实例。
5. 提交事务,调用 commit()方法来完成。

AnotherRightFragment fragment = new AnotherRightFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.right_layout, fragment);
ftransaction.addToBackStack(null);
transaction.commit();

FragmentTransaction

Fragment 的动态添加、删除等操作都需要借助于 FragmentTransaction 类来完成,比如上面提到的 replace() 操作。FragmentTransaction 提供有很多方法供开发人员操作 Activity 里面的 Fragment,这里介绍几个常用的关键方法:

a、获取FragmentManage的方式:
- getFragmentManager() // v4中,getSupportFragmentManager
b、主要的操作都是FragmentTransaction的方法
- FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务
- transaction.add() 往Activity中添加一个Fragment
- transaction.remove() 从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈(回退栈后面会详细说),这个Fragment实例将会被销毁。
- transaction.replace() 使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体~
- transaction.hide()隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
- transaction.show()显示之前隐藏的Fragment
- detach()将此Fragment从Activity中分离,会销毁其布局,但不会销毁该实例
- attach()将从Activity中分离的Fragment,重新关联到该Activity,重新创建其视图层次
- transatcion.commit()//提交一个事务

上述,基本是操作Fragment的所有的方式了,在一个事务开启到提交可以进行多个的添加、移除、替换等操作。

值得注意的是:如果你喜欢使用Fragment,一定要清楚这些方法,哪个会销毁视图,哪个会销毁实例,哪个仅仅只是隐藏,这样才能更好的使用它们。

a、比如:我在FragmentA中的EditText填了一些数据,当切换到FragmentB时,如果希望会到A还能看到数据,则适合你的就是hide和show;也就是说,希望保留用户操作的面板,你可以使用hide和show,当然了不要使劲在那new实例,进行下非null判断。
b、再比如:我不希望保留用户操作,你可以使用remove(),然后add();或者使用replace()这个和remove,add是相同的效果。
c、remove和detach有一点细微的区别,在不考虑回退栈的情况下,remove会销毁整个Fragment实例,而detach则只是销毁其视图结构,实例并不会被销毁。那么二者怎么取舍使用呢?如果你的当前Activity一直存在,那么在不希望保留用户操作的时候,你可以优先使用detach。

通信方式

通常,Fragment 与 Activity 通信存在三种情形:Activity 操作内嵌的 Fragment,Fragment 操作宿主 Activity,Fragment 操作同属 Activity中的其他 Fragment。

由于 Activity 持有所有内嵌的 Fragment 对象实例(创建实例时保存的 Fragment 对象,或者通过 FragmentManager 类提供的 findFragmentById() 和 findFragmentByTag() 方法也能获取到 Fragment 对象),所以可以直接操作Fragment;Fragment 通过 getActivity() 方法可以获取到宿主 Activity 对象(强制转换类型即可),进而可以操作宿主 Activity;那么很自然的,获取到宿主 Activity 对象的 Fragment 便可以操作其他 Fragment 对象。

虽然上述操作已经能够解决 Activity 与 Fragment 的通信问题,但会造成代码逻辑紊乱的结果,极度不符合这一编程思想:高内聚,低耦合。Fragment 做好自己的事情即可,所有涉及到 Fragment 之间的控制显示等操作,都应交由宿主 Activity 来统一管理。

对于Fragment于Activity之间的通信,我们建议的方式是面向接口编程,在Fragment中getActivity获取到的Activity实例应该是实现了我们某个接口的实例,即在Fragment的代码中不应该出现某个具体的Activity类。

Fragment中声明回调接口并声明该接口类型变量,在onAttach方法中把宿主Activity赋给该变量。(宿主Activity须实现回调接口)

public class MyFragment extends Fragment{
    public interface MyFragmentInterface
    {
        public void testMethod(String string);
    }

    private MyFragmentInterface myFragmentInterface;


    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        myFragmentInterface = (MyFragmentInterface)activity;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.layout,container,false);
        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        Button button = (Button)getActivity().findViewById(R.id.button2);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myFragmentInterface.testMethod("from my fragment");
            }
        });
    }
}

Fragment生命周期

Fragment的4个状态
1. 运行状态 当一个碎片是可见的,并且它所关联的活动正处于运行状态时,该碎片也处于运行
状态。
2. 暂停状态 当一个活动进入暂停状态时(由于另一个未占满屏幕的活动被添加到了栈顶),与
它相关联的可见碎片就会进入到暂停状态。
3. 停止状态
当一个活动进入停止状态时,与它相关联的碎片就会进入到停止状态。或者通过调 用 FragmentTransaction 的 remove()、replace()方法将碎片从活动中移除,但有在事务提 交之前调用 addToBackStack()方法,这时的碎片也会进入到停止状态。总的来说,进入 停止状态的碎片对用户来说是完全不可见的,有可能会被系统回收。
4. 销毁状态
碎片总是依附于活动而存在的,因此当活动被销毁时,与它相关联的碎片就会进入 到销毁状态。或者通过调用 FragmentTransaction 的 remove()、replace()方法将碎片从活 动中移除,但在事务提交之前并没有调用 addToBackStack()方法,这时的碎片也会进入 到销毁状态。

这里写图片描述

  • onAttach()
    fragment已经关联到activity,这个时候 activity已经传进来了, 获得activity的传递的值 就可以进行 与activity的通信里, 当然也可以使用getActivity(),前提是这个fragment已经和宿主的activity关联,并且没有脱离,他只调用一次。

  • onCreate()
    系统创建fragment的时候回调他,在他里面实例化一些变量
    这些个变量主要是:当你 暂停 停止的时候 你想保持的数据

  • onCreateView()
    第一次使用的时候 fragment会在这上面画一个layout出来, 为了可以画控件 要返回一个 布局的view,也可以返回null。当系统用到fragment的时候 fragment就要返回他的view,越快越好 ,所以尽量在这里不要做耗时操作,比如从数据库加载大量数据显示listview。

  • onActivityCreated()
    当Activity中的onCreate方法执行完后调用。当执行onActivityCreated()的时候 activity的onCreate才刚完成。所以在onActivityCreated()调用之前 activity的onCreate可能还没有完成,所以不能再onCreateView()中进行 与activity有交互的UI操作,UI交互操作可以在onActivityCreated()里面进行。

  • onStart()
    和activity一致,启动Fragement 启动时回调,,此时Fragement可见。

  • onResume()
    和activity一致 在activity中运行是可见的。激活, Fragement 进入前台, 可获取焦点时激活。

  • onPause()
    和activity一致 其他的activity获得焦点,这个仍然可见
  • onStop()
    和activity一致, fragment不可见的, 可能情况:activity被stopped了OR fragment被移除但被,加入到回退栈中,一个stopped的fragment仍然是活着的如果长时间不用也会被移除。
  • onDestroyView()
    Fragment中的布局被移除时调用。表示fragemnt销毁相关联的UI布局, 清除所有跟视图相关的资源。
  • onDestroy()
    销毁fragment对象, 跟activity类似了。
  • onDetach()
    Fragment和Activity解除关联的时候调用。 脱离activity。

有时候我们使用Fragment,是因为考虑到使用它进行界面切换比Activity切换的代价要小很多。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值