Fragment使用详解

Fragment角色分析
Fragment是Android 3.0引入的新API。Fragment意思是片段,Activity就像是一个商店,Fragment就像是顾客,顾客在商店里才能实现顾客的身份和对应功能,商店关门(销毁),顾客身份就也不在了,顾客可以有自己的挑选商品,付费,自己离开等自己的行为。
所以梳理下来就是,Fragment必须依赖Activity生存,Fragment有自己的生命周期和操控事件,但是他的存亡依赖于父Activity。(Activity生命周期结束,他也就不存在了)

应用Fragment的意义何在
既然Fragment必须依赖Activity,为什么还要双层嵌套,这不是更浪费资源?

A Fragment is a piece of an application's user interface or behavior that can be placed
 in an Activity. Interaction with fragments is done through FragmentManager, which can
  be obtained via Activity.getFragmentManager() and Fragment.getFragmentManager(). 

官方文档有说通过FragmentManager可以更方便的替换Fragment,意思就是顾客的身份可以随时更替,不用新建Fragment所在的Activity,以往我们如果新换功能性界面是不是都需要更换Activity,那么有了Fragment,就可以动态改变当前Fragment,而他原来的Activity并么有动,Fragment的优点就是高复用性。加入我们要的界面Item过多,我们每次点击Item都会新实例化一个Activity,而相比使用Fragment来说,我们就实例化一个Activity就足够了。

Fragment实例
平时创建Activity需要继承AppCompatActivity基类,Fragmnet类似需要继承基类:
这里写图片描述
平时比较常用的是DialogFragment(对话框)、ListFragment(列表)、PreferenceFragment(选项设置)、WebViewFragment(WebView界面)。

FragmentDemo.java

public class FragmentDemo extends Fragment {


    public FragmentDemo() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 加载layout布局
        return inflater.inflate(R.layout.fragment_fragment_demo, container, false);
    }

}

布局文件:

<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"
    tools:context="com.alphathink.fragmentdemo.FragmentDemo">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment" />

</FrameLayout>

主Activity布局文件添加Fragment(用name属性添加):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.alphathink.fragmentdemo.MainActivity">

    <fragment
        android:name="com.alphathink.fragmentdemo.FragmentDemo"
        android:id="@+id/fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

这样一个fragment布局就填好了。
运行结果:
这里写图片描述


进阶,模仿QQ下方点击换界面
简单效果:
这里写图片描述

实现也很简单,没有做相应的图片资源,所以将就一下吧:

代码,我也不贴了,有需要的下载来看就是了。地址是:
http://download.csdn.net/download/z_dinghao/9830344

注意与Activity区别较大的是:我们更换Activity是使用Intent方式来跳转,他需要调用Transaction的方式来增删操作fragment。

        //从父Activity中获取FragmentManager管理器
        FragmentManager fragmentManager = getSupportFragmentManager();
        //调用FragmentManager的FragmentTransaction食物处理器来统一处理fragment的相关操作
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        fragment_first = new FragmentFirst();
        transaction.replace(R.id.mContent,fragment_first);
        transaction.commit();

常用方法:add()、replace()、show()、attach()、remove()、hide()、detach()、commit()。


以上也只是搭建了一个简易的框架而已,各个fragment里边都是只有一句话,什么事务也没有。如果我们想在里边做些自己的事怎么做呢?其实这点就和平常的Activity中做的类似,不过还有点小区别。比如我们想在第一个fragment中设置按钮点击toast一句话这一简单操作,就要这样改第一个FragmentFirst.java

修改FragmentFirst.java

public class FragmentFirst extends Fragment {
    private Button btn_test;


    public FragmentFirst() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 修改前,只是加载了布局文件
        //return inflater.inflate(R.layout.fragment_fragment_first, container, false);

        //修改后的操作改变
        View view;
        view = inflater.inflate(R.layout.fragment_fragment_first, container, false);
        //这里好比Activity的OnCreate()方法之后,我们在他返回View之前把自己的操作加入进去就好,注意findViewById的方式
        initViewId(view);
        return view;
    }

    public void initViewId(View view){
        //别忘了View参数,否则空指针了哦
        btn_test = (Button) view.findViewById(R.id.btn_test);
        btn_test.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //fragment中获取当前上下文使用getActivity() 即可
                Toast.makeText(getActivity(),"你点击了按钮",Toast.LENGTH_SHORT).show();
            }
        });
    }

}

布局文件就不贴了,改动的东西不多,自己试验一下即可,需要注意的也表明了,其他想要实现的功能和在Activity中类似,以此类推即可。

在调用commit()之前,可以将事务添加到fragment事务后台栈中(通过调用addToBackStatck()压栈,通过popBackStack()出栈)。这个后台栈由activity管理,并且允许用户通过按BACK键回退到前一个fragment状态。可以利用这个实现一些比如新闻界面的fragment,可以浏览历史记录。



添加Fragment的两种方式

  • xml布局添加
  • java代码中添加
    其实上边我们已经分别实现过了两种方式:
    方式一是在xml布局文件中通过指定fragment的name属性来指定fragment。
    方式二是通过replace方法来替换GroupView实现我们的目的fragment。

Fragment的生命周期
这里写图片描述

试验fragment:

public class FragmentFirst extends Fragment {


    public FragmentFirst() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.d("test","onCreateView");
        return inflater.inflate(R.layout.fragment_fragment_first, container, false);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.d("test","onAttach");
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("test","onCreate");
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d("test","onActivityCreated");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d("test","onStart");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d("test","onResume");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d("test","onPause");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d("test","onStop");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d("test","onDestroyView");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("test","onDestroy");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.d("test","onDetach");
    }
}

这里测试我们使用第二种方式,用replace方法代替ViewGroup的方式来看看日志:

启动Activity:

05-01 12:01:24.425 21507-21507/com.alphathink.fragmentdemo D/test: onAttach
05-01 12:01:24.425 21507-21507/com.alphathink.fragmentdemo D/test: onCreate
05-01 12:01:24.425 21507-21507/com.alphathink.fragmentdemo D/test: onCreateView
05-01 12:01:24.426 21507-21507/com.alphathink.fragmentdemo D/test: onActivityCreated
05-01 12:01:24.426 21507-21507/com.alphathink.fragmentdemo D/test: onStart
05-01 12:01:24.427 21507-21507/com.alphathink.fragmentdemo D/test: onResume

点击home键:

05-01 12:01:45.579 21507-21507/com.alphathink.fragmentdemo D/test: onPause
05-01 12:01:45.896 21507-21507/com.alphathink.fragmentdemo D/test: onStop

重新进入:

05-01 12:02:00.574 21507-21507/com.alphathink.fragmentdemo D/test: onStart
05-01 12:02:00.575 21507-21507/com.alphathink.fragmentdemo D/test: onResume

退出键:

05-01 12:04:18.315 21507-21507/com.alphathink.fragmentdemo D/test: onPause
05-01 12:04:19.087 21507-21507/com.alphathink.fragmentdemo D/test: onStop
05-01 12:04:19.087 21507-21507/com.alphathink.fragmentdemo D/test: onDestroyView
05-01 12:04:19.087 21507-21507/com.alphathink.fragmentdemo D/test: onDestroy
05-01 12:04:19.087 21507-21507/com.alphathink.fragmentdemo D/test: onDetach
  • onAttach():fragment被依附到Activity上调用,只被调用一次。
  • onCreate():fragment创建调用
  • onCreateView():创建、绘制该fragment调用
  • onActivityCreated():fragment依附的Activity启动后调用
  • onStart():fragment启动调用
  • onResume():fragment显示时调用
  • onPause():暂停fragment调用
  • onStop():停止fragment调用
  • onDestroyView():销毁fragment所包含的View时视图调用
  • onDestroy():销毁fragment调用,只调用一次
  • onDetach():fragment从Activity中解绑时调用,只会调用一次

结合log我们可以体会下fragment的生命周期,比activity稍微多了几个方法。



Fragment与Activity的交互

  • Activity向Fragment传送数据:利用Bundle,调用fragment的Fragment.setArguments(Bundle bundle)方法传递
  • Fragment向Activity传递数据,需要在Fragment定义回调接口,Activity实现Fragment的回调接口CallBacks即可。
  • Activity还可引用无界面的Fragment,要添加没有界面的fragment ,可使用add(Fragment, String)(为fragment提供一个唯一的标识string,而不是视图(view)ID)。这样添加了fragment,但是,因为还没有关联到activity布局中的视图(view) ,收不到onCreateView()的调用。所以不需要实现这个方法。  对于无界面fragment,字符串标签是唯一识别它的方法。如果之后想从activity中取到fragment,需要使用findFragmentByTag()。
  • 在Fragment中可以通过getActivity得到当前绑定的Activity的实例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值