Android之---Fragment介绍

Fragment:Activity碎片(必须嵌套在Activity中使用)。

一、Fragment生命周期简介:

因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activity是密切相关的。

如果Activity是暂停状态,其中所有的Fragment都是暂停状态;如果Activity是stopped状态,这个Activity中所有的Fragment都不能被启动;如果Activity被销毁,那么它其中的所有Fragment都会被销毁。

但是,当Activity在活动状态,可以独立控制Fragment的状态,比如加上或者移除Fragment。

当这样进行fragment transaction(转换)的时候,可以把fragment放入Activity的back stack中,这样用户就可以进行返回操作。

使用Fragment时,需要继承Fragment或者Fragment的子类(DialogFragment, ListFragment, PreferenceFragment, WebViewFragment),所以Fragment的代码看起来和Activity的类似。

每当创建一个Fragment时,首先添加以下三个回调方法:

  • onCreate():系统在创建Fragment的时候调用这个方法,这里应该初始化相关的组件,一些即便是被暂停或者被停止时依然需要保留的东西。
  • onCreateView():当第一次绘制Fragment的UI时系统调用这个方法,该方法将返回一个View,如果Fragment不提供UI也可以返回null。注意,如果继承自ListFragment,onCreateView()默认的实现会返回一个ListView,所以不用自己实现。
  • onPause():当用户离开Fragment时第一个调用这个方法,需要提交一些变化,因为用户很可能不再返回来。

将Fragment加载到Activity当中有两种方式:
方式一:添加Fragment到Activity的布局文件当中
方式二:在Activity的代码中动态添加Fragment(
第一种方式虽然简单但灵活性不够。添加Fragment到Activity的布局文件当中,就等同于将Fragment及其视图与activity的视图绑定在一起,且在activity的生命周期过程中,无法切换fragment视图。

第二种方式比较复杂,但也是唯一一种可以在运行时控制fragment的方式(加载、移除、替换)。

二、Fragment生命周期详解:

先看看官方文档中的图片:
这里写图片描述

再看看activity和fragment生命周期的对比图:
这里写图片描述

实例:在MainActivity中添加一个Fragment(完整代码如下)

Fragment布局:fragment01.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:orientation="vertical" >

    <RatingBar
        android:id="@+id/ratingBar1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

</LinearLayout>

Fragment类:MyFragment.java

package com.example.m01_fragmentlifecycle;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MyFragment extends Fragment {
    private final String TAG = "MyFragment";

    //获得activity的传递的值
    @Override
    public void onAttach(Activity activity) {
        // TODO Auto-generated method stub
        super.onAttach(activity);
        Log.i(TAG, "--MyFragment->>onAttach");
    }

    //实例化成员变量
    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        Log.i(TAG, "--MyFragment->>onCreate");
    }

    //给当前的fragment绘制UI布局,可以使用线程更新UI
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Log.i(TAG, "--MyFragment->>onCreateView");
        View view = inflater.inflate(R.layout.fragment01, null);
        // TODO Auto-generated method stub
        return view;
    }

    //表示activity执行oncreate方法完成了的时候会调用此方法
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);
        Log.i(TAG, "--MyFragment->>onActivityCreated");
    }

    //和activity一致
    @Override
    public void onStart() {
        // TODO Auto-generated method stub
        super.onStart();
        Log.i(TAG, "--MyFragment->>onStart");
    }

    //和activity一致
    @Override
    public void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        Log.i(TAG, "--MyFragment->>onResume");
    }

    //和activity一致
    @Override
    public void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        Log.i(TAG, "--MyFragment->>onPause");
    }

    //和activity一致
    @Override
    public void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
        Log.i(TAG, "--MyFragment->>onStop");
    }

    //表示fragment销毁相关联的UI布局
    @Override
    public void onDestroyView() {
        // TODO Auto-generated method stub
        super.onDestroyView();
        Log.i(TAG, "--MyFragment->>onDestroyView");
    }

    //销毁fragment对象
    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        Log.i(TAG, "--MyFragment->>onDestroy");
    }

    //脱离activity
    @Override
    public void onDetach() {
        // TODO Auto-generated method stub
        super.onDetach();
        Log.i(TAG, "--MyFragment->>onDetach");
    }
}

Activity布局: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="horizontal"
    tools:context=".MainActivity" >

    <LinearLayout
        android:id="@+id/line"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    </LinearLayout>

</LinearLayout>

Activity类:MainActivity.java

package com.example.m01_fragmentlifecycle;

import android.os.Bundle;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.util.Log;
import android.view.Menu;

public class MainActivity extends Activity {
    private final String TAG = "MainActivity";
    private FragmentManager manager;
    private FragmentTransaction transaction;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        manager = getFragmentManager();
        transaction = manager.beginTransaction();
        MyFragment fragment = new MyFragment();
        transaction.add(R.id.line, fragment);
        transaction.commit();
        Log.i(TAG, "--MainActivity->>onCreate");
    }

    @Override
    protected void onStart() {
        // TODO Auto-generated method stub
        super.onStart();
        Log.i(TAG, "--MainActivity->>onStart");
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        Log.i(TAG, "--MainActivity->>onResume");
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        Log.i(TAG, "--MainActivity->>onPause");
    }

    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
        Log.i(TAG, "--MainActivity->>onStop");
    }

    @Override
    protected void onRestart() {
        // TODO Auto-generated method stub
        super.onRestart();
        Log.i(TAG, "--MainActivity->>onRestart");
    }
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        Log.i(TAG, "--MainActivity->>onDestroy");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

上面类中的各生命周期阶段的方法里边都打印了日志,运行看日志如下:

初次加载:
这里写图片描述
这里写图片描述

点击一下HOME键或者接入电话:
这里写图片描述

重新进入程序或者接电话完毕:
这里写图片描述

点击back退出程序:
这里写图片描述

通过上面的日志,我们能够看出,Fragment和Activity的生命周期太相似了。只是有几个Activity中没有的新方法,需要重点介绍一下:

  • onAttach方法:Fragment和Activity建立关联的时候调用(获得activity的传递的值)
  • onCreateView方法:为Fragment创建视图(加载布局)时调用(给当前的fragment绘制UI布局,可以使用线程更新UI)
  • onActivityCreated方法:当Activity中的onCreate方法执行完后调用(表示activity执行oncreate方法完成了的时候会调用此方法)
  • onDestroyView方法:Fragment中的布局被移除时调用(表示fragment销毁相关联的UI布局)
  • onDetach方法:Fragment和Activity解除关联的时候调用(脱离activity)

三、Fragment返回栈的管理:

假设现在我们有两个Fragment:Fragment01和Fragment02,我们现在从Fragment01的界面跳到Fragment02,然后按Back键,发现程序是直接退出了,而不是返回到Fragment01。如果现在想实现以下功能:从Fragment01的界面跳到Fragment02,然后按Back键,会返回到Fragment01。这个功能该怎么实现呢?这其实就利用到了返回栈的知识。

其实很简单,FragmentTransaction中提供了一个addToBackStack()方法,可以将一个事务添加到返回栈中。

我们先回顾一下之前动态加载Fragment的代码,然后在此基础之上,增加一行代码就可以将Fragment添加到返回栈中:(即第07行代码)

//步骤一:添加一个FragmentTransaction的实例
FragmentManager fragmentManager =getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
//步骤二:用add()方法加上Fragment的对象
RightFragment rightFragment = new RightFragment();
transaction.add(R.id.right, rightFragment); transaction.addToBackStack(null);
//步骤三:调用commit()方法使得FragmentTransaction实例的改变生效
transaction.commit();

第07行代码:我们在事务提交之前调用了FragmentTransaction的addToBackStack()方法,它可以接受一个名字用于描述返回栈的状态,,一般传入null即可。

实例:现在通过代码来实现以下界面(下面的图片为程序运行时加载的首页),并且把每一个Fragment都加入到返回栈当中去,然后观察其生命周期的变化。完整代码如下:

这里写图片描述

首先新建工程文件m01_Fragment04,然后开始我们的代码之旅:

我们先把右侧的四个Fragment建起来吧:

Fragment01.java主要部分的代码如下:

package com.example.m01_fragment04;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment01 extends Fragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

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

为避免啰嗦,这里就不把Fragment01生命周期中的其他函数罗列出来了,我们只要知道在实际代码中这些函数都是加了的。

Fragment01的布局文件f1.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:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="加载图片" />

</LinearLayout>

然后依次新建出Fragment02、Fragment03、Fragment04的java代码和布局文件。

MainActivity的布局文件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"
    tools:context=".MainActivity" >

    <LinearLayout
        android:id="@+id/left"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:background="#CCCCCC"
        android:orientation="vertical" >

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="加载图片" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="海报管理" />

        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="照片管理" />

        <Button
            android:id="@+id/button4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="新闻管理" />        

    </LinearLayout>

    <LinearLayout
        android:id="@+id/right"       
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical" >
    </LinearLayout>

</LinearLayout>

其中,第一个LinearLayout表示左侧的按钮,第二个LinearLayout留给右边的Fragment。

MainActivity.java的代码如下:

package com.example.m01_fragment04;

import android.os.Bundle;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity  implements OnClickListener{

    private FragmentManager manager;
    private FragmentTransaction transaction;
    private Button button1,button2,button3,button4;

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

    manager = getFragmentManager();
        button1 = (Button)this.findViewById(R.id.button1);
        button1.setOnClickListener(this);
        button2 = (Button)this.findViewById(R.id.button2);
        button2.setOnClickListener(this);
        button3 = (Button)this.findViewById(R.id.button3);
        button3.setOnClickListener(this);
        button4 = (Button)this.findViewById(R.id.button4);
        button4.setOnClickListener(this);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    //通过点击不同的按钮,跳转到不同的Fragment
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        transaction = manager.beginTransaction();
        switch (v.getId()) {
        case R.id.button1:
            Fragment01 fragment01 = new Fragment01();
            transaction.replace(R.id.right, fragment01, "fragment01");
            transaction.addToBackStack("fragment01");// 添加到Activity管理的回退栈中。
            break;

        case R.id.button2:
            Fragment02 fragment02 = new Fragment02();
            transaction.replace(R.id.right, fragment02, "fragment02");
            transaction.addToBackStack("fragment02");// 添加到Activity管理的回退栈中。
            break;

        case R.id.button3:
            Fragment03 fragment03 = new Fragment03();
            transaction.replace(R.id.right, fragment03, "fragment03");
            transaction.addToBackStack("fragment03");// 添加到Activity管理的回退栈中。
            break;

        case R.id.button4:
            Fragment04 fragment04 = new Fragment04();
            transaction.replace(R.id.right, fragment04, "fragment04");
            transaction.addToBackStack("fragment04");// 添加到Activity管理的回退栈中。
            break;
        }
        transaction.commit();        
    }

}

上当代码中,通过点击不同的按钮,就能跳到对应的Fragment,而这四个Fragment都已经加入到了返回栈当中。运行程序之后,也是这样的。

注意第46行和第72行,transaction = manager.beginTransaction()意味着开始,transaction.commit()意味着结束。

我们就其中的fragment01和fragment02来讨论一下他们的生命周期的变化:

运行程序后,界面如下,没有任何fragment被加载:
这里写图片描述

点击左侧第一个按钮,加载fragment01:
这里写图片描述

点击左侧第二个按钮,加载fragment02(此时fragment01被替换,并且被压倒了栈中):
这里写图片描述
注:如果fragment01在替换的时候没有被压到栈中,那就会被销毁,在执行完onDestroyView()方法后,会继续执行onDestroy()和onDetach()方法。

按back键fragment01回到屏幕(fragment02被销毁):
这里写图片描述

再按back键,fragment01被销毁:
这里写图片描述

注:Fragment的返回栈由Activity管理;而Activity的返回栈由系统管理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值