Android Fragment 生命周期以及基本用法(一)

Fragment 生命周期(一)

Fragment两种加载方式及ViewPage(二)

Fragment 传递数据的三种方法(三)

1.基本概念


1)Fragment是什么,有什么用?

答:Fragment是可以让你的app纵享丝滑的设计,如果你的app想在现在基础上性能大幅度提高,并且占用内存降低,同样的界面Activity占用内存比Fragment要多,响应速度Fragment比Activty在中低端手机上快了很多,甚至能达到好几倍!如果你的app当前或以后有移植平板等平台时,可以让你节省大量时间和精力。

下图是文档中给出的一个Fragment分别对应手机与平板间不同情况的处理图:

PS:简单的新闻浏览页面,使用两个Fragment分别显示新闻列表与新闻内容;

2)Fragmeng优点

  • Fragment可以使你能够将activity分离成多个可重用的组件,每个都有它自己的生命周期和UI。
  • Fragment可以轻松得创建动态灵活的UI设计,可以适应于不同的屏幕尺寸。从手机到平板电脑。
  • Fragment是一个独立的模块,紧紧地与activity绑定在一起。可以运行中动态地移除、加入、交换等。
  • Fragment提供一个新的方式让你在不同的安卓设备上统一你的UI。
  • Fragment 解决Activity间的切换不流畅,轻量切换。
  • Fragment 替代TabActivity做导航,性能更好。
  • Fragment 在4.2.版本中新增嵌套fragmeng使用方法,能够生成更好的界面效果。
  • Fragment做局部内容更新更方便,原来为了到达这一点要把多个布局放到一个activity里面,现在可以用多Fragment来代替,只有在需要的时候才加载Fragment,提高性能

3)Fragment的生命周期图

可以看到Fragment比Activity多了几个额外的生命周期回调方法:

onAttach:onAttach()在fragment与Activity关联之后调调查用。需要注意的是,初始化fragment参数可以从getArguments()获得,但是,当Fragment附加到Activity之后,就无法再调用setArguments()。所以除了在最开始时,其它时间都无法向初始化参数添加内容。

onCreate:fragment初次创建时调用。尽管它看起来像是Activity的OnCreate()函数,但这个只是用来创建Fragment的。此时的Activity还没有创建完成,因为我们的Fragment也是Activity创建的一部分。所以如果你想在这里使用Activity中的一些资源,将会获取不到。比如:获取同一个Activity中其它Frament的控件实例。(代码如下:),如果想要获得Activity相关联的资源,必须在onActivityCreated中获取。

onCreateView:在这个fragment构造它的用户接口视图(即布局)时调用。

onActivityCreated:在Activity的OnCreate()结束后,会调用此方法。所以到这里的时候,Activity已经创建完成!在这个函数中才可以使用Activity的所有资源。如果把下面的代码放在这里,获取到的btn_Try的值将不会再是空的!

onStart:当到OnStart()时,Fragment对用户就是可见的了。但用户还未开始与Fragment交互。在生命周期中也可以看到Fragment的OnStart()过程与Activity的OnStart()过程是绑定的。意义即是一样的。以前你写在Activity的OnStart()中来处理的代码,用Fragment来实现时,依然可以放在OnStart()中来处理。

onResume:当这个fragment对用户可见并且正在运行时调用。这是Fragment与用户交互之前的最后一个回调。从生命周期对比中,可以看到,Fragment的OnResume与Activity的OnResume是相互绑定的,意义是一样的。它依赖于包含它的activity的Activity.onResume。当OnResume()结束后,就可以正式与用户交互了。

onPause:此回调与Activity的OnPause()相绑定,与Activity的OnPause()意义一样。

onStop:这个回调与Activity的OnStop()相绑定,意义一样。已停止的Fragment可以直接返回到OnStart()回调,然后调用OnResume()。

onDestroyView:如果Fragment即将被结束或保存,那么撤销方向上的下一个回调将是onDestoryView()。会将在onCreateView创建的视图与这个fragment分离。下次这个fragment若要显示,那么将会创建新视图。这会在onStop之后和onDestroy之前调用。这个方法的调用同onCreateView是否返回非null视图无关。它会潜在的在这个视图状态被保存之后以及它被它的父视图回收之前调用。

onDestroy:当这个fragment不再使用时调用。需要注意的是,它即使经过了onDestroy()阶段,但仍然能从Activity中找到,因为它还没有Detach。

onDetach:Fragment生命周期中最后一个回调是onDetach()。调用它以后,Fragment就不再与Activity相绑定,它也不再拥有视图层次结构,它的所有资源都将被释放。

2.创建一个Fragment

1)静态加载Fragment

实现流程:

示例代码:

Step 1:定义两个Fragment的布局,就是fragment显示内容的(两个都一样,所以这里就贴一个)

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> 

Step 2:自定义一个Fragment类,需要继承Fragment或者他的子类,重写onCreateView()方法 在该方法中调用:inflater.inflate()方法加载Fragment的布局文件,接着返回加载的view对象,我们分别创建两个fragment的布局,分别是Fragmentone,Fragmenttwo,因为都一样所以就贴一个

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

注意,使用的V4包中的Fragment!这里的代码主要就是加载了我们刚刚写好的fragment1.xml布局文件并返回。同样的方法,我们再写好Fragment2

Step 3:在需要加载Fragment的Activity对应的布局文件中添加fragment的标签, 记住,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.harvic.com.harvicblog2.Fragment1"  
        android:layout_width="0dip"  
        android:layout_height="match_parent"  
        android:layout_weight="1" />  
  
    <fragment  
        android:id="@+id/fragment2"  
        android:name="com.harvic.com.harvicblog2.Fragment2"  
        android:layout_width="0dip"  
        android:layout_height="match_parent"  
        android:layout_weight="1" />  
  
</LinearLayout>  

Step 4: Activity在onCreate( )方法中调用setContentView()加载布局文件即可!

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

2)动态加载Fragment

实现流程:

打开activity_main.xml,将其中代码全部删除,改成下面的样子:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:orientation="vertical"  
    android:baselineAligned="false" >  
  
    <Button  
        android:id="@+id/btn_show_fragment1"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:text="显示Fragment1"/>  
  
    <Button  
        android:id="@+id/btn_show_fragment2"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:text="显示Fragment2"/>  
  
    <FrameLayout  
        android:id="@+id/fragment_container"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"/>  
  
</LinearLayout> 

主界面上有两个按钮和一个FrameLayout布局。这两个按钮分别用来在这个FrameLayout加载Fragment1和Fragment2的实例。效果如下:

(由于在录GIF时,绿色会出问题,所以把fragment1的背景改成了紫色)

image

其它代码都没有动,主要的是在MainActivity里,点击这两个按钮时做的处理:

MainActivity

public class MainActivity extends FragmentActivity {  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
  
        Button btnLoadFrag1 = (Button)findViewById(R.id.btn_show_fragment1);  
        btnLoadFrag1.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                FragmentManager manager = getSupportFragmentManager();  
                FragmentTransaction transaction = manager.beginTransaction();  
                Fragment1 fragment1 = new Fragment1();  
                transaction.add(R.id.fragment_container, fragment1);  
                transaction.commit();  
            }  
        });  
  
        Button btnLoagFrag2 = (Button)findViewById(R.id.btn_show_fragment2);  
        btnLoagFrag2.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                FragmentManager manager = getSupportFragmentManager();  
                FragmentTransaction transaction = manager.beginTransaction();  
                Fragment2 fragment2 = new Fragment2();  
                transaction.add(R.id.fragment_container, fragment2);  
                transaction.commit();  
            }  
        });  
    }  
}  

看上面的代码很容易明白,在点击按钮时都做了类似的操作:

FragmentManager manager = getSupportFragmentManager();  
FragmentTransaction transaction = manager.beginTransaction();  
Fragment1 fragment1 = new Fragment1();  
transaction.add(R.id.fragment_container, fragment1);  
transaction.commit();  

动态添加Fragment主要分为4步:
1.获取到FragmentManager,在V4包中通过getSupportFragmentManager,在系统中原生的Fragment是通过getFragmentManager获得的。
2.开启一个事务,通过调用beginTransaction方法开启。
3.向容器内加入Fragment,一般使用add或者replace方法实现,需要传入容器的id和Fragment的实例。
4.提交事务,调用commit方法提交。
这部分有关fragment的操作看不大懂也没关系,下节我们会具体讲有关Fragment的管理!

3.Fragment管理与Fragment事务

4.Fragment与Activity的交互

1)组件获取

Fragment获得Activity中的组件 getActivity().findViewById(R.id.list);
Activity获得Fragment中的组件(根据id和tag都可以) getFragmentManager.findFragmentByid(R.id.fragment1);

2)数据传递

①Activit传递数据给Fragment:

在Activity中创建Bundle数据包,调用Fragment实例的setArguments(bundle) 从而将Bundle数据包传给Fragment,然后Fragment中调用getArguments获得 Bundle对象,然后进行解析就可以了

②Fragment传递数据给Activity

在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity实现该回调接口, Fragment就可以通过回调接口传数据了,回调,相信很多人都知道是什么玩意,但是 写不出来啊,网上的一百度"fragment传数据给Activity",全是李刚老师的那个代码,真心无语 算了,这里就写下局部代码吧,相信读者一看就懂的了:

Step 1:定义一个回调接口:(Fragment中)
/*接口*/  
public interface CallBack{  
    /*定义一个获取信息的方法*/  
    public void getResult(String result);  
}  
Step 2:接口回调(Fragment中)
/*接口回调*/  
public void getData(CallBack callBack){  
    /*获取文本框的信息,当然你也可以传其他类型的参数,看需求咯*/  
    String msg = editText.getText().toString();  
    callBack.getResult(msg);  
}  
Step 3:使用接口回调方法读数据(Activity中)
/* 使用接口回调的方法获取数据 */  
leftFragment.getData(new CallBack() {  
 @Override  
       public void getResult(String result) {              /*打印信息*/  
            Toast.makeText(MainActivity.this, "-->>" + result, 1).show();  
            }
        }); 
③Fragment与Fragment之间的数据互传

其实这很简单,找到要接受数据的fragment对象,直接调用setArguments传数据进去就可以了 通常的话是replace时,即fragment跳转的时候传数据的,那么只需要在初始化要跳转的Fragment 后调用他的setArguments方法传入数据即可!
如果是两个Fragment需要即时传数据,而非跳转的话,就需要先在Activity获得f1传过来的数据, 再传到f2了,就是以Activity为媒介~
MainActivity

//[1]获取fragment管理者 
        FragmentManager fragmentManager = getFragmentManager();
        //[2]开启一个事物
        FragmentTransaction beginTransaction = fragmentManager.beginTransaction();
        
        //[2.1]替换fragment
        beginTransaction.replace(R.id.ll1, new Fragment1(),"f1");
        beginTransaction.replace(R.id.ll2, new Fragment2(),"f2");
        
        
        //[3]开启事物
        beginTransaction.commit();

Fragment1()和Fragment2()一样,只写个Fragment1()

public class Fragment1 extends Fragment {

    //当系统第一次画ui的时候调用   通过这个方法方法可以让Fragment显示自己的布局内容
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        
        //通过打气筒把一个布局转换成一个View对象
        View view = inflater.inflate(R.layout.fragment1, null);
        
        //[1]找到按钮 设置点击事件 
        view.findViewById(R.id.btn_update).setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                
                //[2]修改fragment2里面的内容  通过fragment的公共桥梁 --->activity
                Fragment2 fragment2 =  (Fragment2) getActivity().getFragmentManager().findFragmentByTag("f2");
 
                fragment2.updateText("哈哈哈呵呵");
                
            }
        });
        return view;
    }
}

Fragment详解(二)

Fragment详解(二)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,392评论 25 707
  • 引言:这篇文章,大概分析下Fragment的生命周期、实际应用方法以及使用Fragment时需要注意的地方,算是F...
    androidjp阅读 12,849评论 10 104
  • Fragment 描述:   翻译可以译为:碎片、片段,Android 3.0开始引入fragments 的概念;...
    Lost_Robot阅读 1,680评论 0 11
  • 磕头,到底是磕给谁的? 这个问题是个大哉问。 或许,话可以这样讲: 每个人都有一个他自己的宇宙。 他跟一切事物的关...
    j_haven阅读 212评论 0 0
  • 你真的长得并不好看 小眼睛 有瑕疵的脸和斑斑点点的四肢 加上浮肿的身材 PLANK 慢跑或者跳操 瘦到55斤为止 ...
    Alexia阅读 265评论 0 2