Android开发 —Fragment片段布局

前言

Fragment想必我们不生疏吧,在日常支出中,对于Fragment的行使也很频仍,现在主流的APP中,基本的架构也都是一个主页,然后每个Tab项用Fragment做布局,差异取舍做切换,使用起来也造福。可是还是不是对它有丰盛的认识吗,谷歌(谷歌)引荐用Fragment来代表Activity,但又不曾显明说怎么要用Fragment来替代Activity,那里就掀起顶牛了,那究竟是要不要用,是不是采纳Fragment完全替换Activity真的比常规开发情势更可以吗?借使要用的话,那需求了然怎么要运用Fragment,Fragment是哪些,它的生命周期如何,怎样运用,通讯又是什么样,有哪些毛病吗?带着那些题材,我们逐一去解读。

目录

  • Fragment为啥要用
  • Fragment是什么
  • Fragment生命周期
  • Fragment怎么用
  • Fragment通信
  • Fragment是还是不是很全面
  • 小结
  • 参照地址

Fragment为啥要用

Fragment是Android 3.0
(Honeycomb)被引入的。紧要目标是为着给大屏幕(如平板统计机)上进一步动态和灵活的UI设计提供支撑。由于机械统计机的显示器比手机的显示器大过多,由此可用来组合和调换的UI组件的半空中更大,利用Fragment完毕此类设计的时,就无需治本对视图层次结构的扑朔迷离更改。

通过将 Activity 布局分成片段,您可以在运转时修改 Activity 的外观,并在由
Activity
管理的回来栈中保留这一个改动。即使单纯唯有Activity布局,那是不够的,不仅在哥哥大上有一套布局,同时在平板上还索要规划一套布局,那样维护起来也麻烦,代码上也有必然的冗余,对于APP包的尺寸也有自然的压力。Fragment的优势是布局在分裂装备上的适配。

比如:

图片 1

从图中大家得以见见,在机械中,一个Activity
A包括了多少个Fragment,分别是Fragment A和Fragment
B,但在二哥大中呢,就必要三个Activity,分别是Activity A包罗Fragment
A和Activity B包蕴Fragment
B。同时每个Fragment都拥有友好的一套生命周期回调方法,并分别处理自己的用户输入事件。
由此,在机械中利用一个Activity 就可以了,左侧是列表,左边是内容详情。

除外,使用Fragment还有如此多少个地方优势:

  • 代码复用。越发适用于模块化的开发,因为一个Fragment可以被三个Activity嵌套,有个同步的业务模块就足以复用了,是模块化UI的佳绩组件。
  • Activity用来治本Fragment。Fragment的生命周期是依托到Activity中,Fragment可以被Attach添加和Detach释放。
  • 可控性。Fragment可以像经常对象那样自由的创始和操纵,传递参数越发便于和造福,也不用处理系统相关的工作,呈现方式、替换、不管是完全依旧有的,都可以形成相应的更动。
  • Fragments是view
    controllers,它们含有可测试的,解耦的工作逻辑块,由于Fragments是构建在views之上的,而views很简单完结动画效果,由此Fragments在显示屏切换时享有更好的支配。

Fragment是什么

说了半天的Fragment,也观望如此多次Fragment那么些名词出现,那么Fragment到底是怎么东东啊?定义又是如何?

Fragment也得以叫为“片段”,但本身觉得“片段”普通话叫法有点生硬,仍然维持叫Fragment比较好,它可以象征Activity中的行为或用户界面部分。我们得以在一个Activity中用三个Fragment组合来构建多窗格的UI,以及在八个Activity中重复使用某个Fragment。它有谈得来的生命周期,能经受自己的输入,并且可以在
Activity 运行时添加或删除Fragment(有点像在分化 Activity 中重复使用的“子
Activity”)。

简简单单的话,Fragment其实可以明白为一个负有温馨生命周期的控件,只但是这些控件又微微特殊,它有和好的拍卖输入事件的力量,有自己的生命周期,又无法不借助于Activity,能相互通讯和托管。

Fragment生命周期

如图:

图片 2

这张图是Fragment生命周期和Activity生命周期比较图,可以见见双方仍旧有那个形似的地点,比如都有onCreate(),onStart(),onPause(),onDestroy()等等,因为Fragment是被托管到Activity中的,所以多了三个onAttach()和onDetach()。这里讲讲与Activity生命周期分裂等的不二法门。

onAttach()

Fragment和Activity建立关系的时候调用,被增大到Activity中去。

onCreate()

系统会在创设Fragment时调用此办法。可以初阶化一段资源文件等等。

onCreateView()

系统会在Fragment首次绘制其用户界面时调用此方式。 要想为Fragment绘制
UI,从该格局中回到的 View 必须是Fragment布局的根视图。假诺Fragment未提供
UI,您能够回来 null。

onViewCreated()

在Fragment被绘制后,调用此办法,可以初步化控件资源。

onActivityCreated()

当onCreate(),onCreateView(),onViewCreated()方法执行完后调用,也就是Activity被渲染绘制出来后。

onPause()

系统将此措施作为用户距离Fragment的第四个信号(但并不总是意味着此Fragment会被销毁)进行调用。
平日可以在此方法内肯定在时下用户会话甘休后依然有效的其余变动(因为用户可能不会回到)。

onDestroyView()

Fragment中的布局被移除时调用。

onDetach()

Fragment和Activity解除关系的时候调用。

但要求注一点是:除了onCreateView,其他的具有办法如若您重写了,必须调用父类对于该方法的完毕。

再有相似在起步Fragment的时候,它的生命周期就会举办那多少个章程。

图片 3

Fragment怎么用

前边介绍了半天,不耐烦的人会说,这么多废话,也丢失的到底是怎么样利用,毕竟大家是开发者,需求的采纳方法,那么现在就来说说用法怎么样呢。三种方法:静态用法和动态用法。

静态用法

1、继承Fragment,重写onCreateView决定Fragemnt的布局

2、在Activity中扬言此Fragment,就当和平时的View一样

先是是布局文件:fragment1.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:background="#00ff00" >  

    <TextView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="This is fragment 1"  
        android:textColor="#000000"  
        android:textSize="25sp" />  

</LinearLayout>  

可以见见,这一个布局文件万分简单,唯有一个LinearLayout,里面加入了一个TextView。大家再新建一个fragment2.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:background="#ffff00" >  

    <TextView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="This is fragment 2"  
        android:textColor="#000000"  
        android:textSize="25sp" />  

</LinearLayout>  

接下来新建一个类Fragment1,那个类是三番五次自Fragment的:

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

可以见到,在onCreateView()方法中加载了fragment1.xml的布局。同样fragment2.xml也是同一的做法,新建一个Fragment2类:

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

下一场打开或新建activity_main.xml作为主Activity的布局文件,在内部参与三个Fragment的引用,使用android:name前缀来引用具体的Fragment:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:baselineAligned="false" >  

    <fragment  
        android:id="@+id/fragment1"  
        android:name="com.example.fragmentdemo.Fragment1"  
        android:layout_width="0dip"  
        android:layout_height="match_parent"  
        android:layout_weight="1" />  

    <fragment  
        android:id="@+id/fragment2"  
        android:name="com.example.fragmentdemo.Fragment2"  
        android:layout_width="0dip"  
        android:layout_height="match_parent"  
        android:layout_weight="1" />  

</LinearLayout>  

最终新建MainActivity作为程序的主Activity,里面的代码极度简单,都是自动生成的:

public class MainActivity extends Activity {  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
    }  
}  

前日我们来运行三次程序,就会看出,一个Activity很友好地蕴藏了七个Fragment,那四个Fragment平分了百分之百显示器,效果图如下:
图片 4

动态用法

上边仅仅是Fragment不难用法,它的确有力部分是在动态地添加到Activity中,那么动态用法又是哪些呢?

照旧在静态用法代码的基本功上改动,打开activity_main.xml,将里面对Fragment的引用都剔除,只保留最外层的LinearLayout,并给它添加一个id,因为大家要动态添加Fragment,不用在XML里添加了,删除后代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:id="@+id/main_layout"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:baselineAligned="false" >  

</LinearLayout>  

下一场打开MainActivity,修改其中的代码如下所示:

public class MainActivity extends Activity {  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        Display display = getWindowManager().getDefaultDisplay();  
        if (display.getWidth() > display.getHeight()) {  
            Fragment1 fragment1 = new Fragment1();  
            getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment1).commit();  
        } else {  
            Fragment2 fragment2 = new Fragment2();  
            getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment2).commit();  
        }  
    }  

}  

总的来看了没,首先,大家要获取屏幕的幅度和惊人,然后开展判定,若是显示器宽度领先中度就添加fragment1,即使中度领先宽度就添加fragment2。动态添加Fragment紧要分为4步:

1.获得到FragmentManager,在Activity中得以一向通过getFragmentManager得到。

2.敞开一个工作,通过调用beginTransaction方法开启。

3.向容器内出席Fragment,一般选择replace方法完成,必要传入容器的id和Fragment的实例。

4.提交工作,调用commit方法提交。

今天运行一下主次,效果如下图所示:

图片 5

图片 6

要想治本 Activity 中的片段,需求使用 FragmentManager。要想取得它,需要Activity 调用 getFragmentManager()。

行使 FragmentManager 执行的操作包含:

  • 经过 findFragmentById()(对于在 Activity 布局中提供 UI
    的有的)或 findFragmentByTag()(对于提供或不提供 UI 的局地)获取
    Activity 中存在的局地
  • 经过 popBackStack()将一部分从重临栈中弹出
  • 因而 addOnBackStackChangedListener() 注册一个侦听重返栈变化的侦听器

也足以拔取 FragmentManager 打开一个 FragmentTransaction,通过它来执行某些事情,如添加和删除片段。

Fragment通信

即使 Fragment 是用作单身于 Activity的靶子已毕,并且可在多少个 Activity
内接纳,但Fragment 的给定实例会直接绑定到含有它的
Activity。具体地说,Fragment 可以通过 getActivity() 访问 Activity实例,并轻松地执行在
Activity 布局中寻觅视图等任务。如:

View listView = getActivity().findViewById(R.id.list);

同等地,Activity
也足以利用 findFragmentById() 或 findFragmentByTag(),通过从 FragmentManager 获取对 Fragment 的引用来调用Fragment中的方法。例如:

ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);

始建对 Activity 的风浪回调

在少数意况下,可能需求经过与 Activity
共享事件。执行此操作的一个好点子是,在Fragment 内定义一个回调接口,并须要宿主
Activity 完结它。 当 Activity
通过该接口收到回调时,能够根据必要与布局中的其他Fragment共享那么些音信。

比如说,倘诺一个资讯应用的 Activity 有多少个Fragment
,一个用于浮现小说列表(Fragment A),另一个用来浮现小说(Fragment
B)—,那么Fragment A必须在列表项被选定后报告
Activity,以便它报告Fragment B 突显该小说。
在本例中,OnArticleSelectedListener 接口在一部分 A 内表明:

public static class FragmentA extends ListFragment { 
    public interface OnArticleSelectedListener { 
        public void onArticleSelected(Uri articleUri);
    } 
} 

下一场,该Fragment的宿主 Activity
会达成 OnArticleSelectedListener 接口并取代 onArticleSelected(),未来自Fragment
A 的轩然大波通报Fragment B。为确保宿主 Activity 完成此界面,Fragment A
的 onAttach() 回调方法(系统在向 Activity
添加Fragment时调用的点子)会通过更换传递到 onAttach() 中的 Activity 来实例化 OnArticleSelectedListener 的实例:

public static class FragmentA extends ListFragment { 
    OnArticleSelectedListener mListener;
    @Override 
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try { 
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
        } 
    } 
} 

假设 Activity
未已毕界面,则有的会引发 ClassCastException。完结时,mListener 成员会保留对
Activity 的 OnArticleSelectedListener 落成的引用,以便Fragment A
可以经过调用 OnArticleSelectedListener 界面定义的点子与 Activity
共享事件。例如,若是Fragment A
是 ListFragment 的一个扩展,则用户每一次点击列表项时,系统都会调用Fragment中的 onListItemClick(),然后该方法会调用 onArticleSelected() 以与
Activity 共享事件:

public static class FragmentA extends ListFragment {
    OnArticleSelectedListener mListener;
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
        mListener.onArticleSelected(noteUri);
    }
}

Fragment是还是不是很周全

因为Fragment是由FragmentManager来管理,每一个Activity有一个FragmentManager,管理着一个Fragment的栈,Activity是系统级其余,由系统来管理ActivityManager,栈也是系统范围的。而Fragment则是各类Activity范围内的,所以在选拔Fragment的时候也有几点要注意。

  • 同一个Activity中,只可以有一个ID或TAG标识的Fragment实例。
    那很简单了解,同一个限量内,有标识的实例肯定是要唯一才行(否则还要标识干嘛)那一个在布局中时时犯错,在布局中写Fragment最好永不加ID或者TAG,否则很不难现身不允许创制的荒唐。我的尺度是若是放在布局中,就毫无加ID和TAG,要是急需ID和TAG就全用代码控制。创造新实例前先到FragmentManager中搜索一番,那也正是有标识的意思所在。
  • 一个Activity中有一个Fragment池,实例不必然会被灭绝,可能会保留在池中。
    那一个跟第一点大概。就好比系统会缓存Activity的实例一样,FragmentManager也会缓存Fragment实例,以方便和加速再一次体现。
  • FragmentManager的效果范围是一体Activity,所以,某一个搭架子ID,不可能重复被Fragment替换。
    日常彰显Fragment有两种艺术,一种是层叠到某个布局上,或者把某部布局方面的Fragment替换掉,不过那么些布局不可能冒出二次,比如布局A中有ID为id的区域,要来得为Fragment,此布局A,只可以在一个Activity中显示一个,否则首个id区域不可以被Fragment成功替换。因为虽有二个ID布局的实例,但ID是同一的,对FragmentManager来说是同一的,它会觉得只有一个,因为它看的是布局的ID,而不是布局的实例。
  • Fragment的生命周期反应Activity的生命周期。
    Fragment在呈现和退出时会走一回完整的生命周期。其它,正在突显时,就跟Activity的一样,Activity被onPause,里面的Fragment就onPause,以此类推,因而拉动的问题尽管,比如你在onStart()里面做了一部分作业,那么,当宿主Activity被屏蔽,又出现时(比如接了个电话),Fragment的onStart也会被高到,所以你要想开,那几个生命周期不单单在显示和剥离时会走到。
  • Fragment的可知性。
    本条题目应运而生在有Fragment栈的时候,也就是说每个Fragment不清楚自己是或不是确实对用户可知。比如现在是Fragment
    A,又在其上边突显了Fragment
    B,当B呈现后,A并不知道自己上边还有一个,也不知底自己对用户不可知了,同样再有一个C,B也不知。C退出后,B如故不知自己已在栈顶,对用户可知,B退后,A也不知。也就是说Fragment呈现或者退出,栈里的别样Fragment不可能感知。那一点就不如Activity,a被b盖住后,a会走到onStop(),同样c彰显后,b也能透过onStop()感知。Fragment可以从FragmentManager监听BackStackState的浮动,但它只报告您Stack变了,不报告你是多了,仍然少,还有你处的地方。有一个化解方案就是,记录页面的Path深度,再跟Fragment所在的Stack深度来相比较,如若相同,那么那些Fragment就在栈顶。因为种种页面的Path深度是原则性的,而Stack深度是不转移的,所以这么些能确切的论断Fragment是或不是对用户可知,当然,这几个仅针对所有页面有效,对于布局中的一个区域是无效的。
  • Fragment的风云传递。
    对此层叠的Fragment,其实就相当于在一个FrameLayout里面添加一堆的View,所以,若是处在顶层的Fragment没处理点击事件,那么事件就会向下层传递,直到事件被处理。比如有二个Fragment
    A和B,B在A上边,B只有TextView且没处理事件,那么点击B时,会意识A里的View处理了事件。那一个对于Activity也不会生出,因为事件无法跨窗体传播,上面的Activity没处理事件,也不会传给下边的Activity,即便它可见。解决之法,就是让地点的Fragment的根布局吃掉事件,为各样根ViewGroup添加onClick=“true”。
  • 与第三方Activity交互。与第三方相互,仍要拔取Android的业内startActivityForResult()和onActivityResult()那二个点子来举办。但对此Fragment有些业务须要留意,Fragment也有那二个章程,可是为了能科学的让Fragment收到onActivityResult(),须求:
  1. 宿主Activity要兑现一个空的onActivityResult(),里面调用super.onActivityResult()
  2. 调用Fragment#startActivityForResult()而不是用Activity的
    当然,也足以一贯动用Activity的startActivityForResult(),那样的话,就只可以在宿主Activity里处理回来的结果了。

小结

在用法的代码部分参考郭神的博客,感觉郭神在代码讲解部分通俗易懂,看起来也利于。可想而知,在动用Fragment也有一部分注意事项,不是那么完美的,即使谷歌引进大家用Fragment来取代Activity来使用,大家也的确那做了,现在中央主流的APP也都是少量Activity+浩大Fragment,但也急需幸免有些坑慎入

 

正文摘自:https://www.cnblogs.com/cr330326/p/5712022.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注