概述

本文以一个简单的小例子,简述在Android开发中,Fragment的常见用法,仅供学习分享使用,如有不足之处,还请指正。

什么是Fragment?

Fragment代表一个功能或者用户界面的一部分。一个Activity可以由多个Fragment组成多窗格UI,一个Fragment也可以重用在多个Activity中。你可以把Fragment作为Activity的一个模块,它有自己的生命周期,接收自己的 输入事件,当Activity运行时可以动态的添加和删除,类似于‘sub Activity’。

Fragment必须始终作为Activity的一部分,它的生命周期受到宿主Activity生命周期的影响。如:当Activity暂停时,其包含的所有Fragment也都会暂停;当Activity销毁时,其包含的所有Fragment也会被销毁;但是当Activity运行时,你可以独立的操作Fragment,如添加和删除;

Fragment设计理念

android在android 3.0(api等级11)中引入了Fragment,主要是为了支持大屏幕(如平板电脑)上更具活力和灵活性的ui设计。因为平板电脑的屏幕比手机大得多,所以有更多的空间来组合和交换ui组件。通过将Activity的布局划分为Fragment,就能够在程序运行时修改Activity的外观,并在由活动管理的后堆栈中保存这些更改。

例如,一个新闻应用App,可以用一个Fragment显示左侧的文章列表,用另一个Fragment显示右侧的文章----两个Fragment同时出现在一个Activity中,而每个Fragment都有自己的生命周期及回调方法集合,并处理自己的用户输入事件。因此,用户可以在相同的Activity中选择文章,而不是分开单独使用不同的Activity,如图1的平板版式所示。

应该将每个Fragment设计成模块化和可重用的页面组件。也就是说,由于每个Fragment有自己的生命周期,回调函数,布局和行为,所以可以在多个Activity中包含同一个Fragment。Fragment应该设计为重用,避免在一个Fragment中直接操作引用另一个Fragment。这一点特别重要,因为一个模块化的Fragment可以通过不同的组合来适应不同屏幕大小。在应用程序同时支持平板电脑和手机时,可以在不同的布局配置中重用Fragment,以根据屏幕空间优化用户体验。

图1一个例子,说明两个由Fragment定义的UI模块如何在平板上设计为一个Activity中显示,但在手机上则分开显示。

涉及知识点

涉及知识点如下:

  • Fragment 所有自定义Fragment的父类。
  • FragmentManager Fragment管理器对象,用来动态新增和替换Fragmentd对象。
  • FragmentTransaction 表示一个Fragment管理事务,必须以commit()结束。
  • onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 方法,返回Fragment对应的布局视图。
  • getFragmentManager() 返回一个Fragment管理器对象。

创建一个Fragment

如果要创建一个自定义Fragment,必须创建一个Fragment的子类,并且必须实现onCreateView()方法,通过LayoutInflater将布局文件填充到Fragment中,如下所示:

 public class RightFragment extends Fragment {

     private TextView tvMsg;

     @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
Log.i("TAG", "------------Right-----------onCreateView: ");
View view= inflater.inflate(R.layout.fragment_right, container, false);
tvMsg= (TextView) view.findViewById(R.id.tv_msg);
return view;
}
}

Fragment生命周期

Fragment的生命周期和Activity的生命周期有许多相似之处。如下图所示:

Activity和Fragment回调函数输出内容如下所示:

 05-30 22:16:02.207 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onAttach:
05-30 22:16:02.207 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onCreate:
05-30 22:16:02.207 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onCreateView:
05-30 22:16:02.216 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onAttach:
05-30 22:16:02.216 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onCreate:
05-30 22:16:02.216 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onCreateView:
05-30 22:16:02.218 29479-29479/com.hex.demofragment E/TAG: ------------Main-----------onCreate:
05-30 22:16:02.218 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onActivityCreated:
05-30 22:16:02.218 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onActivityCreated:
05-30 22:16:02.219 29479-29479/com.hex.demofragment E/TAG: ------------Main-----------onStart:
05-30 22:16:02.219 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onStart:
05-30 22:16:02.219 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onStart:
05-30 22:16:02.224 29479-29479/com.hex.demofragment E/TAG: ------------Main-----------onResume:
05-30 22:16:02.224 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onResume:
05-30 22:16:02.224 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onResume:
05-30 22:16:06.188 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onPause:
05-30 22:16:06.188 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onPause:
05-30 22:16:06.189 29479-29479/com.hex.demofragment E/TAG: ------------Main-----------onPause:
05-30 22:16:06.756 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onStop:
05-30 22:16:06.756 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onStop:
05-30 22:16:06.756 29479-29479/com.hex.demofragment E/TAG: ------------Main-----------onStop:
05-30 22:16:06.757 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onDestroyView:
05-30 22:16:06.757 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onDestroy:
05-30 22:16:06.757 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onDetach:
05-30 22:16:06.757 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onDestroyView:
05-30 22:16:06.757 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onDestroy:
05-30 22:16:06.757 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onDetach:
05-30 22:16:06.757 29479-29479/com.hex.demofragment E/TAG: ------------Main-----------onDestroy:

Activity中添加Fragment

Fragment是作为Activity的一部分而存在的,有两种方法可以将Fragment添加到Activity的布局文件中:

静态添加Fragment

在Activity的布局文件中直接声明Fragment,在这种情况下,您可以为Fragment指定布局属性,就像它是视图控件一样。例如,这里是包含两个片段的活动的布局文件:

 <?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="horizontal"
tools:context="com.hex.demofragment.MainActivity">
<fragment
android:tag="left"
android:id="@+id/left_fragment"
class="com.hex.demofragment.LeftFragment"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_weight="1"></fragment>
<fragment
android:tag="right"
android:id="@+id/right_fragment"
class="com.hex.demofragment.RightFragment"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_weight="2"></fragment>
</LinearLayout>

如上所示:class 表示需要在视图中显示的fragment类,当系统创建Activity时,就会实例化Fragment并调用onCreateView方法,显示对应的布局文件。android:name和class表示的功能是一样的,需要其中一个即可。

备注:每个Fragment都需要一个唯一的标识符,如果Activity被重新启动的话,系统可以用它来恢复Fragment。

有三种方法可以为Fragment提供id:

  • 提供android:id带有唯一的ID属性。
  • 提供android:tag带有唯一字符串的标签属性。
  • 如果没有提供前面两个中的任何一个,系统将使用容器视图的id。
动态添加Fragment

当Activity处于运行状态时,都可以将Fragment添加到页面布局中,只需要有一个ViewGroup用来存放即可。如下所示:

 //FragmentManager是Activity内部用来与Fragment进行交互的接口
FragmentManager fm = getFragmentManager();
FragmentTransaction ft=fm.beginTransaction();
//将左侧Fragment和Frame控件关联起来
left=new LeftFragment();
left.setTransData(transData);
ft.add(R.id.fl_left,left);
right=new RightFragment();
ft.add(R.id.fl_right,right);
ft.commit();

如果要管理Activity中的Fragment,需要使用碎片管理器(FragmentManager),可以通过Activity中的getFragmentManager()方法来获得对象。

Fragment之间的传值

Fragment 作为独立的可重用的用户模块,应尽量避免相互引用,所以如何实现之间相互传值,就显得很重要,本文采用接口回调的方式进行传值。

具体如下:

1、定义一个传值接口,如下所示:

 public interface ITransData {
public void transData(Bundle bundle);
}

2、在需要传值的Fragment中,定义接口属性对象,如下所示,左侧(LeftFragment):

 private ITransData mTransData;

 public void setTransData(ITransData transData){
this.mTransData=transData;
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_left, container, false);
Button tv= (Button) view.findViewById(R.id.bn_left);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mTransData!=null){
Bundle bundle=new Bundle();
bundle.putString("name","我是左边");
mTransData.transData(bundle);
}
}
});
return view;
}

3、在Activity中,实现ITransData接口,并传给LeftFragment进行调用:

 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
ITransData transData=new TransData();
//FragmentManager是Activity内部用来与Fragment进行交互的接口
FragmentManager fm = getFragmentManager();
FragmentTransaction ft=fm.beginTransaction();
//将左侧Fragment和Frame控件关联起来
left=new LeftFragment();
left.setTransData(transData);//将接口传递给LeftFragment
ft.add(R.id.fl_left,left);
right=new RightFragment();
ft.add(R.id.fl_right,right);
ft.commit();
}

4、在接口函数中调用获取左侧传回来的值,并调用RightFragment方法传递值。

 protected class TransData implements ITransData
{
@Override
public void transData(Bundle bundle) {
String name=bundle.getString("name","空");
if(right!=null){
right.setTransData(name);
}
}
}

至此Fragment之间传值介绍完毕,总结一句话:Fragment通过接口传值,接口的实现在Activity中,实现松耦合。

备注

沧海月明珠有泪,蓝田日暖玉生烟。

一起学Android之Fragment的更多相关文章

  1. Android基础——Fragment与Activity交互

    今天继续讲解Fragment组件的特性,主要是跟Activity的交互和生命周期的关系,我们前面已经说过Fragment是依赖于Activity的,而且生命周期也跟Activity绑定一起.下面我们看 ...

  2. Android学习——Fragment静态加载

    从今天开始做一套安卓的学习笔记,开发环境是Android Studio,把学习过程中的知识和遇到的问题都写在这里,先从Fragment开始学起. Fragment概述 Fragment是Android ...

  3. Android:Activity+Fragment及它们之间的数据交换.

    Android:Activity+Fragment及它们之间的数据交换 关于Fragment与Fragment.Activity通信的四种方式 比较好一点的Activity+Fragment及它们之间 ...

  4. Android中Fragment和ViewPager那点事儿(仿微信APP)

    在之前的博文<Android中使用ViewPager实现屏幕页面切换和引导页效果实现>和<Android中Fragment的两种创建方式>以及<Android中Fragm ...

  5. Android中Fragment与Activity之间的交互(两种实现方式)

    (未给Fragment的布局设置BackGound) 之前关于Android中Fragment的概念以及创建方式,我专门写了一篇博文<Android中Fragment的两种创建方式>,就如 ...

  6. Android中Fragment的两种创建方式

    fragment是Activity中用户界面的一个行为或者是一部分.你可以在一个单独的Activity上把多个Fragment组合成为一个多区域的UI,并且可以在多个Activity中再使用.你可以认 ...

  7. Android开发学习之路-该怎么学Android(Service和Activity通信为例)

    在大部分地方,比如书本或者学校和培训机构,教学Android的方式都基本类似,就是告诉先上原理方法,然后对着代码讲一下. 但是,这往往不是一个很好的方法,为什么? ① 学生要掌握这个方法的用途,只能通 ...

  8. 菜鸟学Android编程——简单计算器《一》

    菜鸟瞎搞,高手莫进 本人菜鸟一枚,最近在学Android编程,网上看了一些视频教程,于是想着平时手机上的计算器应该很简单,自己何不尝试着做一个呢? 于是就冒冒失失的开撸了. 简单计算器嘛,功能当然很少 ...

  9. 学Android开发,入门语言java知识点

    学Android开发,入门语言java知识点 Android是一种以Linux为基础的开源码操作系统,主要使用于便携设备,而linux是用c语言和少量汇编语言写成的,如果你想研究Android,就去学 ...

随机推荐

  1. HttpWebRequest 知识点

    string Url = System.Configuration.ConfigurationManager.AppSettings["CallPaperInvoiceURL"]; ...

  2. andorid 查看OpenCv Mat的Debug信息

    在进行Android调试时,不能再Console显示Debug信息,只能在LogCat上显示,显示信息如下图: 代码段: public void printMat2Txt(Mat ElemM, Str ...

  3. 【剑指Offer】10、矩形覆盖

      题目描述:   我们可以用2 X 1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2 X 1的小矩形无重叠地覆盖一个2 X n的大矩形,总共有多少种方法?   解题思路:   我们可以以2 X ...

  4. [系统资源]/proc/meminfo和free输出解释

    High Level statistics RHEL 5, RHEL 6 and RHEL 7 MemTotal: Total usable memory MemFree: The amount of ...

  5. [luogu4161 SCOI2009]游戏 (DP)

    传送门 Solution 可以发现实际上是把n分为几个循环节,然后找循环节的\(lcm\)是这次的排数 而\(lcm\)必然是一些最高次幂的质数的成积,那么就dp求一下所有情况就好了 PS:注意并不是 ...

  6. MySql数据库的一些基本操作---------------SQL语法

    MySql数据库是比较常用的关系型数据库,操作用的是sql语句,下面来说一说MySql的一些基本操作 MySql数据库是一种C/S型的模式,即客户端/服务器端,对应到具体应用上,便是bin目录下的my ...

  7. jQuery源码分析 开篇(一)

    解读一个开源框架,最终目的当然就是学习程序的设计思想和实现技巧. JavaScript宗旨就是Write Less, Do More,简洁的API,优雅的链式,强大的查询与便捷的操作都是我们喜欢他的原 ...

  8. d正则表达式相关

    控件看Delphi正则表达式使用方法(TPerlRegEx)的介绍: 使用正则表达式获取Sql查询语句各项(表名.字段.条件.排序) 希望在线测试正则表达式  在线正则表达式测试 有许多常规表达式 希 ...

  9. 第五节、矩阵分解之LU分解

    一.A的LU分解:A=LU 我们之前探讨过矩阵消元,当时我们通过EA=U将A消元得到了U,这一节,我们从另一个角度分析A与U的关系 假设A是非奇异矩阵且消元过程中没有行交换,我们便可以将矩阵消元的EA ...

  10. ubuntu-kill命令-杀死进程

    显示进程pid ps -A 杀进程的命令 kill -s 9 xxx(进程pid)