Android Fragment详解

来源:互联网 发布:简单java游戏源代码 编辑:程序博客网 时间:2024/06/07 01:04

Fragment是在Android 3.0 (API level 11)开始引入新的API技术。为了提高代码重用性和改善用户体验,我们将Activity中的UI组件进行分组和模块化管理。这些分组后的UI组件就是Fragment

API中对Fragment的介绍:一个Activity页面中可以包含多个Fragment模块,而同一个Fragment模块也可以被多个Activity使用。每个Fragment有自己的布局,有自己的生命周期。虽然Fragment拥有自己的生命周期,但因为Fragment必须被嵌入到Activity中使用,因此Fragment的生命周期是受其Activity宿主的生命周期所控制的。当Activity暂停时,该Activtiy内的所有Fragment都会暂停;当Activity被销毁时,该Activity内的所有Fragment都会被销毁。

Fragment的两大特性:1,局部内容切换 2,UI模块的布局和代码的重用。

虽然Fragment是为平板而提出的,但目前已经完全融入到了手机设备上,如我们常用的设置、微信、QQ等等,都可以看到Fragment的踪影。其效果如下图:




生命周期方法:

1、onAttach(): 当该Fragment被添加到Activity时被回调。该方法只会被调用一次;

2、onCreate(): 当创建Fragment时被回调。该方法只会被调用一次;

3、onCreateView():每次创建、绘制该Fragment的View组件时回调该方法,Fragment将会显示该方法返回的View 组件;

4、onActivityCreated(): 当Fragment的宿主Activity被启动完成后回调该方法;

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

6、onResume(): onStart()方法后一定会回调onResume()方法;

7、onPause(): 暂停Fragment时被回调;

8、onStop(): 停止Fragment时被回调;

9、onDestroyView(): 销毁该Fragment所包含的View组件时调用;

10、onDestroy(): 销毁Fragment时被回调。该方法只会被调用一次;

11、onDetach(): 将Fragment从Activity中删除、替换完成时调用该方法。onDestroy()方法后一定会回调onDetach()方法。该方法只会被调用一次。



(一) 、Fragment的定义:自定义一个类继承于Fragment,如果需要向下兼容的话则继承 android.support.v4.app.Fragment。

必须要实现三个回调函数:

  • onCreate()
  • 系统在创建Fragment的时候调用此方法,这里应该初始化相关的组件。
  • onCreatView()
  • 当第一次绘制Fragment的UI时系统调用这个方法,返回一个View,如果Fragment不提供UI返回null。
  • onPause()
  • 离开Fragment时调用这个方法,需要提交一些变化,防止用户不再回到此页面。

简单示例如下:

<span style="font-size:18px;">public class FirstFragment extends Fragment{    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        //加载此Fragment对应的布局文件,并返回        View view = inflater.inflate(R.layout.fragment, null,false);        return view;    }}</span>


(二)、Fragment的两个重要方法:

1,fragmentTransaction.addToBackStack(null);    点击返回按键的时候会自动回退到上一个fragment
2,popBackStack;  FragmentManager的方法,回退到上一个栈中的fragment

下面的代码是对两个按钮设置监听事件,来响应上面的两个方法:

<span style="font-size:18px;"> @Override    public void onClick(View view) {        if (view.getId() == R.id.btn) {            //FragmentTransaction有一个回退栈            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();            fragmentTransaction.replace(R.id.frame, Fragment2.newInstance());            fragmentTransaction.addToBackStack(null);            fragmentTransaction.commit();        } else if (view.getId() == R.id.btn2) {            getSupportFragmentManager().popBackStack();        }    }</span>

(三)、事务管理:

FragmentManager 功能 : FragmentManager对象可以通过 activity.getFragmentManager()获取;

-- 获取指定 Fragment : 通过findFragmentById()或者findFragmentByTag()方法获取指定Fragment;

-- 弹出栈 : 通过调用 popBackStack(), 将Fragment从后台的栈中弹出;

-- 监听栈 : 通过调用 addOnBackStackChangeListener 注册监听器, 监听后台栈变化; 


FragmentTransaction 对象获取途径 : 

-- 获取 FragmentManager 对象 : 调用 Activity 的 getFragmentManager()获取FragmentManager对象;

-- 获取 FragmentTansaction 对象 : 调用FragmentManager对象的beginTransaction()方法获取FragmentTransaction对象;


FragmentTransaction(Fragment 事务)作用 : 对 Fragement 进行增, 删 , 改操作需要 FragmentTransaction 对象进行操作, 开启这个事务, 获取事务对象, 然后执行对Fragmen的操作, 最后提交事务;

-- 开启事务 :  调用 Fragement 对象的 beginTransaction() 方法可以获取 FragementTransaction 对象;

-- 操作碎片 :  FragmentTransaction 对象中包含了add(), remove(), replace()等方法;

-- 提交操作 :  当执行完Fragement的操作之后, 可以调用 FragementTransaction对象的 commit()方法提交修改;


(四)、Fragment的使用:

1,静态创建Fragment:即在Activity的layout中使用标签<fragment>声明,然后在java代码中通过fragmentManager.findFragmentById()获取到静态fragment对象。

备注:
  • <fragment>标签的android:id 和 android:tag属性必须至少有一个,同一个xml文件中id或tag必须唯一;
  • <fragment>标签的class 和 android:name属性功能完全相同,使用其中任何一个即可,值为自定义Fragment的全路径。
①定义静态Fragment的fragment.xml文件:

<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?><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="com.qianfeng.staticfragment.MainActivity">    <fragment        android:id="@+id/fragment"        android:name="com.qianfeng.staticfragment.StaticFragment"        android:layout_width="match_parent"        android:layout_height="wrap_content"/></LinearLayout></span>


上面使用fragment标签,android:name=”指定一个添加到xml中的Fragment,下面是其对应的具体的Fragment:

public class StaticFragment extends Fragment{    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        //加载此Fragment对应的布局文件,并返回        View view = inflater.inflate(R.layout.fragment, null,false);        return view;    }}

③在MainActivity中获取到静态fragment对象:
<span style="font-size:18px;">public class MainActivity extends AppCompatActivity implements View.OnClickListener, CallBack {    protected TextView mText;    /**     * 通过getSupportFragmentManager获取到一个向下兼容的Fragment管理者     */    private FragmentManager mSupportFragmentManager;    private StaticFragment mStaticFragment;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        super.setContentView(R.layout.activity_main);        mSupportFragmentManager = getSupportFragmentManager();        /**         *findFragmentById,通过id得到Fragment对象         */        mStaticFragment = (StaticFragment) mSupportFragmentManager.findFragmentById(R.id.fragment);        mStaticFragment.setCallBack(this);    }</span>
声明fragment的代码同上,这里不再给出。

2.动态创建Fragment:即在代码中加载Fragment。动态加载Fragment主要是应对fragment切换,相对静态创建Fragment而言,动态创建Fragment使用的更多。下面通过两个页面间的切换来讲解动态Fragment:

①第一个Fragment对应的布局文件fragment.xml:

<span style="font-size:18px;"><?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">    <ImageView        android:id="@+id/iv"        android:src="@mipmap/a"        android:layout_width="wrap_content"        android:layout_height="wrap_content" /></LinearLayout></span><span style="font-size:14px;"></span>
第一个Fragment对应的MyFragment.java类:

<span style="font-size:18px;">package com.example.administrator.myfragment;import android.app.Fragment;import android.os.Bundle;import android.support.annotation.Nullable;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;/** * Created by Administrator on 2016/9/21. */public class MyFragment extends Fragment {    //通过此方法,可以在MainActivity中获得此类的实例    public static MyFragment newInstance() {        Bundle args = new Bundle();        MyFragment fragment = new MyFragment();        fragment.setArguments(args);        return fragment;    }    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View inflate = inflater.inflate(R.layout.fragment, null);        return inflate;    }}</span>
③第二个Fragment对应的布局文件fragment2.xml:
<span style="font-size:18px;"><?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">    <ImageView        android:id="@+id/iv2"        android:src="@mipmap/e"        android:layout_width="wrap_content"        android:layout_height="wrap_content" /></LinearLayout></span>
第一个Fragment对应的MyFragment2.java类:

<span style="font-size:18px;">package com.example.administrator.myfragment;import android.app.Fragment;import android.os.Bundle;import android.support.annotation.Nullable;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;/** * Created by Administrator on 2016/9/21. */public class MyFragment2 extends Fragment {    //通过此方法,可以在MainActivity中获得此类的实例    public static MyFragment2 newInstance() {        Bundle args = new Bundle();        MyFragment2 fragment = new MyFragment2();        fragment.setArguments(args);        return fragment;    }    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View inflate = inflater.inflate(R.layout.fragment2, null);        return inflate;    }}</span><span style="font-size:14px;"></span>
⑤MainActivity.jave代码:

<span style="font-size:18px;">package com.example.administrator.myfragment;import android.app.FragmentTransaction;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.FrameLayout;import android.app.FragmentManager;public class MainActivity extends AppCompatActivity implements View.OnClickListener {    protected FrameLayout fl;    protected Button btn1;    protected Button btn2;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        super.setContentView(R.layout.activity_main);        //初始化控件        initView();        //拿到Fragment管理者        FragmentManager fragmentManager = getFragmentManager();        //创建事务        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();        //把MyFragment中的内容替换到主布局的FrameLayout        fragmentTransaction.replace(R.id.fl, MyFragment.newInstance());        //提交事务        fragmentTransaction.commit();    }    //初始化控件,并对其设置监听事件    private void initView() {        fl = (FrameLayout) findViewById(R.id.fl);        btn1 = (Button) findViewById(R.id.btn1);        btn1.setOnClickListener(MainActivity.this);        btn2 = (Button) findViewById(R.id.btn2);        btn2.setOnClickListener(MainActivity.this);    }    //点击按钮后,调用事务的replace方法,跳转到对应的页面    @Override    public void onClick(View view) {        FragmentManager fragmentManager = getFragmentManager();        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();        if (view.getId() == R.id.btn1) {            fragmentTransaction.replace(R.id.fl, MyFragment2.newInstance());        } else if (view.getId() == R.id.btn2) {            fragmentTransaction.replace(R.id.fl, MyFragment.newInstance());        }        fragmentTransaction.commit();    }}</span>


⑥点击按钮进行切换,效果如下图所示:


0 0