欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解Android开发中Fragment的使用

程序员文章站 2024-03-05 11:41:12
前言 学习java和android将近一年的时间了,期间的成果应该就是独立完成了一个android客户端,并且保证了其在主线版本的稳定性。期间遇到了很多坑,也跟着师兄学到...

前言
学习java和android将近一年的时间了,期间的成果应该就是独立完成了一个android客户端,并且保证了其在主线版本的稳定性。期间遇到了很多坑,也跟着师兄学到了很多android知识。但是人总是要拥抱变化,不能让自己太安逸,虽然有不舍,但是我已经证明了自己的学习能力,下一步就是开始做rom porting了。这里总结一下之前项目中用到最多的fragment。

fragment简介
fragment可以理解成activity中用户界面的一个行为或者一部分,它必须被嵌套在activity中。但是一个fragment有它自己独立的xml布局文件,并且具有良好的封装性,因此特殊情况下fragment可以很容易用activity来进行替换。

创建fragment
创建一个fragment和创建activity类似,需要实现xml布局文件和java class。
xml布局文件和其他布局文件都一样,例如如下所示的布局文件(fragment_layout.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/textview" 
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content" 
   android:text="@string/testview" /> 
  
  <button 
   android:id="@+id/button" 
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content" 
   android:text="@string/button" /> 
  
 </linearlayout> 

java代码中,一般情况下可以根据需要实现fragment以下几个生命周期方法:
1. onattach():当fragment依附于activity时被调用,可以在该方法中获取activity句柄,从而实现fragment和activity之间的通信。
2. oncreate():对fragment做初始化。
3. oncreateview():在第一次为fragment绘制用户界面时系统会调用此方法。
4. onactivitycreated():在宿主activity oncreate函数执行完成之后被调用,可以在这个方法里进行fragment自己的widget实例化和业务逻辑处理。
5. ondestoryview():当fragment开始被销毁时调用。
6. onstart():当fragment可见时被调用。
还有许多其他用以操纵fragment生命周期中各个阶段的回调函数,大家可自行google学习。

fragment生命周期
每一个fragment都有自己的一套生命周期回调方法和处理自己的用户输入事件。对应的生命周期如下图所示:

详解Android开发中Fragment的使用

在activity中加入fragment
首先,需要确保acitivity支持fragment,因此activity通常需要继承自fragmentactivity。在activity中添加fragment通常有两种方法:静态的和动态的。
静态方法
直接在activity的xml布局文件中加入fragment,如下所示:

 

 <?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:baselinealigned="false" 
  android:orientation="horizontal" > 
  
  <fragment 
   android:id="@+id/first" 
   android:name="com.example.fristfragment" 
   android:layout_width="0dp" 
   android:layout_height="match_parent" 
   android:layout_weight="1" /> 
  
  <fragment 
   android:id="@+id/second" 
   android:name="com.example.secondfragment" 
   android:layout_width="0dp" 
   android:layout_height="match_parent" 
   android:layout_weight="1" /> 
  
 </linearlayout> 

<fragment>中的android:name 属性指定了布局中实例化的fragment类
当系统创建activity布局时,它实例化了布局文件中指定的每一个fragment,并且为它们调用oncreateview()函数,以获取每一个fragment的布局。系统直接在<fragment>元素位置插入fragment返回的view
注意:每个fragment都需要一个唯一的标识,如果重启activity,系统可用来恢复fragment(并且用来捕捉fragment的事务处理,例如移除)。为了fragment提供id有三种方法:

  •     用android:id属性提供一个唯一的标识
  •     用android:tag属性提供一个唯一的字符串
  •     如果上述两个属性都没有,系统会使用其容器视图的id

动态方法
使用fragmenttranscation。可以使用fragmenttranscation的api来对activity的fragment进行操作(例如添加,移除,或者替换fragment)。参考代码如下:

 fragmentmanager fragmentmanager = getfragmentmanager() 
 fragmenttransaction fragmenttransaction = fragmentmanager.begintransaction(); 
 examplefragment fragment = new examplefragment(); 
 fragmenttransaction.add(r.id.fragment_container, fragment); 
 fragmenttransaction.commit(); 

传入add()函数的第一个参数是fragment被放置的viewgroup,它由资源id(resource id)指定,第二个参数就是要添加的fragment。一旦通过fragmenttranscation做了更改,都应当使用commit()视变化生效。

fragments通信
fragments之间不应该直接进行通信,它们之间的交互应该通过宿主activity进行。有三种fragment和acitivity交互的方法:
1. activity创建带参数的fragment。
2. activity中保持了fragment的对象句柄,可通过句柄直接调用该fragment的public方法。
3. fragment可在onattach函数中获取定义的listener句柄。
创建带参数的fragment
在某些特定的情况下,fragment可能需要特定的参数来进行初始化。由于fragment必须只有一个无参构造函数,因此可以考虑使用静态的newinstance方法来创建带参数的fragment。示例代码如下:

  

 import android.os.bundle; 
 import android.support.v4.app.fragment; 
  
 public class testfragment extends fragment { 
  public static testfragment newinstance(int num, string title) { 
   testfragment fragment = new testfragment(); 
   bundle args = new bundle(); 
   args.putint("num", num); 
   args.putstring("title", title); 
   fragment.setarguments(args); 
   return fragment; 
  } 
  
  @override 
  public void oncreate(bundle savedinstancestate) { 
   super.oncreate(savedinstancestate); 
  
   int num = getarguments().getint("num", 0); 
   string title = getarguments().getstring("title", ""); 
  } 
  
 } 

你可以在activity里,简单的加载一个带参数的fragment:

 fragmenttransaction ft = getsupportfragmentmanager().begintransaction(); 
 testfragment fragment = testfragment.newinstance(5, "fragment title"); 
 ft.replace(r.id.placeholder, fragment); 
 ft.commit(); 

调用fragment的方法
因为activity可以获取嵌入的fragment的句柄,因此可以直接通过fragment句柄调用该方法。

 public class testfragment extends fragment { 
  public void dosomething(string param) { 
   // do something in fragment 
  } 
 } 

在activity中,可以直接通过fragment的对象句柄调用该方法:

 public class mainactivity extends fragmentactivity { 
  @override 
  public void oncreate(bundle savedinstancestate) { 
   super.oncreate(savedinstancestate); 
   testfragment testfragment = new testfragment(); 
   testfragment.dosomething("some param"); 
  } 
 } 

fragment listener
如果fragment需要共享事件给activity,则需要利用这个方法。fragment中定义一个接口,并且由activity来实现这个接口。在onattach()方法中将实现了这个接口的activity获得到。
在fragment中定义接口代码如下:

   

import android.support.v4.app.fragment; 
  
 public class mylistfragment extends fragment { 
  // ... 
  // define the listener of the interface type 
  // listener is the activity itself 
  private onitemselectedlistener listener; 
  
  // define the events that the fragment will use to communicate 
  public interface onitemselectedlistener { 
  public void onrssitemselected(string link); 
  } 
  
  // store the listener (activity) that will have events fired once the fragment is attached 
  @override 
  public void onattach(activity activity) { 
  super.onattach(activity); 
   if (activity instanceof onitemselectedlistener) { 
   listener = (onitemselectedlistener) activity; 
   } else { 
   throw new classcastexception(activity.tostring() 
    + " must implement mylistfragment.onitemselectedlistener"); 
   } 
  } 
  
  // now we can fire the event when the user selects something in the fragment 
  public void onsomeclick(view v) { 
   listener.onrssitemselected("some link"); 
  } 
 } 

在activity中实现这个接口:

   

import android.support.v4.app.fragmentactivity; 
  
 public class rssfeedactivity extends fragmentactivity implements 
  mylistfragment.onitemselectedlistener { 
  detailfragment fragment; 
  
  @override 
  protected void oncreate(bundle savedinstancestate) { 
   super.oncreate(savedinstancestate); 
   setcontentview(r.layout.activity_rssfeed); 
   fragment = (detailfragment) getsupportfragmentmanager() 
    .findfragmentbyid(r.id.detailfragment); 
  } 
  
  // now we can define the action to take in the activity when the fragment event fires 
  @override 
  public void onrssitemselected(string link) { 
   if (fragment != null && fragment.isinlayout()) { 
    fragment.settext(link); 
   } 
  } 
 }