Android -- Fragment 基本用法矫户、生命周期與細(xì)節(jié)注意

引言:這篇文章,大概分析下Fragment的生命周期磅叛、實(shí)際應(yīng)用方法以及使用Fragment時需要注意的地方屑咳,算是Fragment的入門級文章,理解透Fragment生命周期和一些細(xì)節(jié)弊琴,就容易理解Fragment如何與外界通信等問題了兆龙。至于對其的源碼分析等更加深入的內(nèi)容,本文涉及不多敲董。
Fragment的寫法就不多說了紫皇,一般是繼承Fragment,然后重寫onCreateView方法去與View布局進(jìn)行綁定腋寨。
<u>PS:本人拋磚引玉聪铺,某些方面沒有說明到,還請讀者朋友們多多包容</u>萄窜。

使用前提


FragmentActivity铃剔。使用Fragment,需要Activity繼承自FragmentActivity查刻,并且键兜,為了兼容到Android3.0以前的版本,需要使用v4兼容包下的FragmentActivity穗泵。

示例說明用法


一普气、常見的兩種加載方式

  1. 方式一:直接獲取FragmentManager并使用FragmentManager管理下的FragmentTranscation來進(jìn)行Fragment或者Fragment列表的加載、替換佃延、刪除等操作现诀,此時的Fragment所在的容器一般選擇用FrameLayout。

【關(guān)于FragmentManager和FragmentTranscation】
* FragmentManager:Activity中有個FragmentManager苇侵,其內(nèi)部維護(hù)fragment隊(duì)列赶盔,以及fragment事務(wù)的回退棧企锌。在Fragment被創(chuàng)建榆浓、并由FragmentManager管理時,F(xiàn)ragmentManager就把它放入自己維護(hù)的fragment隊(duì)列中撕攒。
* FragmentTransaction:知道了FragmentManger可以管理和維護(hù)Fragment陡鹃,那么FragmentManager是直接去綁定Fragment然后把它set進(jìn)自己的隊(duì)列中嗎?不是的抖坪,而是用FragmentTransaction(Fragment事務(wù))萍鲸,F(xiàn)ragmentManager調(diào)用beginTransaction()方法返回一個新建的事務(wù),用于記錄對于Fragment的add擦俐、replace等操作脊阴,最終將事務(wù)commit回FragmentManager,才開始啟動執(zhí)行事務(wù)的內(nèi)容,實(shí)現(xiàn)真正的Fragment顯示嘿期。

  1. 方式二:使用ViewPager等容器去裝載Fragment列表并通過他們自己的頁面切換能力去切換Fragment品擎。

【關(guān)于ViewPager適配器相關(guān)類:FragmentPagerAdapter與FragmentStatePagerAdapter】
* FragmentPagerAdapter:對于不再需要的fragment,選擇調(diào)用detach方法备徐,僅銷毀視圖萄传,并不會銷毀fragment實(shí)例。
* FragmentStatePagerAdapter:會銷毀不再需要的fragment蜜猾,當(dāng)當(dāng)前事務(wù)提交以后秀菱,會徹底的將fragment從當(dāng)前Activity的FragmentManager中移除,state標(biāo)明蹭睡,銷毀時衍菱,會將其onSaveInstanceState(Bundle outState)中的bundle信息保存下來,當(dāng)用戶切換回來肩豁,可以通過該bundle恢復(fù)生成新的fragment梦碗,也就是說,你可以在onSaveInstanceState(Bundle outState)方法中保存一些數(shù)據(jù)蓖救,在onCreate中進(jìn)行恢復(fù)創(chuàng)建洪规。
* 總結(jié):<u>使用FragmentStatePagerAdapter當(dāng)然更省內(nèi)存,但是銷毀新建也是需要時間的循捺。一般情況下斩例,如果你是制作主頁面,就3从橘、4個Tab念赶,那么可以選擇使用FragmentPagerAdapter,如果你是用于ViewPager展示數(shù)量特別多的條目時恰力,那么建議使用FragmentStatePagerAdapter叉谜。</u>

(這種方式中ViewPager管理Fragment的原理其實(shí)也是FragmentManager和FragmentTransaction,看下圖源碼就知道)


二踩萎、兩種寫法的關(guān)鍵代碼

  1. 直接獲取FragmentManager和它的FragmentTransaction去將Fragment加載到當(dāng)前界面的指定容器中去的一般寫法:
  2. activity layout布局
  ```

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
…………
<Button
……………………
/>
…………
<FrameLayout
android:id="@+id/frame_root_fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
</LinearLayout>
2. Activity的初始化方法
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
fragmentA = new MyFragmentA();
getSupportFragmentManager().beginTransaction().add(R.id.frame_root_fragment,fragmentA).commit();
}
```

  1. 使用ViewPager去裝載適配Fragment的一般寫法:
  2. activity layout布局
  ```

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
……
/>
<android.support.v4.view.ViewPager
android:id="@+id/vp_main"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
</LinearLayout>
```
2. 初始化方法

  ///在onCreate()中調(diào)用此方法
  private void initView() {
      ///使用LinkedHashMap等方式方便我們管理Fragments
      fragmentMap = new LinkedHashMap<>();
  ///控件初始化
      mTabLayout = (TabLayout) findViewById(R.id.tl_main);
      mViewPager = (ViewPager) findViewById(R.id.vp_main);
      …………
      mPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
          @Override
          public Fragment getItem(int position) {
              switch (position) {
                  case 0:///Fragment一
                  default:
                      if(!fragmentMap.containsKey(titles[0]))
                          fragmentMap.put(titles[0],new DogFragment());
                      return fragmentMap.get(titles[0]);
                  case 1:///Fragment二
                      if(!fragmentMap.containsKey(titles[1]))
                          fragmentMap.put(titles[1],new CatFragment());
                      return fragmentMap.get(titles[1]);
              }
          }

          …………
      };
      mViewPager.setAdapter(mPagerAdapter);
      mTabLayout.setupWithViewPager(mViewPager);
  }

從圖解中分析Fragment的生命周期


下面圖解說明下Fragment的生命周期:

Fragment與宿主Activity的聲明周期方法調(diào)用順序

Fragment生命周期

圖解說明

  • 從圖解可以看到停局,F(xiàn)ragment的一些生命周期方法與Activity比較相似,畢竟Fragment表示“碎片香府、塊”的含義董栽,本身實(shí)現(xiàn)出來一個主要目的就是幫Activity分擔(dān)UI代碼部分的實(shí)現(xiàn)邏輯的。
  • 藍(lán)色背景的生命周期方法:從onCreateView() 到onDestroyView()企孩,在整個Fragment創(chuàng)建到被銷毀的過程中可以不只被執(zhí)行一次锭碳,這里就涉及到管理著Fragment事務(wù)(FragmentTransaction)的FragmentManager底層的后臺記錄棧的東西了。
  • 綠色背景的生命周期方法:在整個Fragment的生命周期中勿璃,僅僅執(zhí)行一次擒抛。
  • 對圖解的補(bǔ)充:這里用幾個例子具體看清Fragment的周期方法的調(diào)用次序推汽,更好地理解Fragment的生命周期:
    • 首先,可以看看本人另一篇博文查漏補(bǔ)缺(二):易忘難懂中的第10點(diǎn):Fragment 與 它所在的Activity的生命周期方法執(zhí)行次序 歧沪,它說明了在ViewPager適配Fragment列表這種方式下Fragment方法執(zhí)行次序民泵。
    • 這里再加上<u>直接在frameLayout上添加、替換Fragment</u>的情況槽畔,進(jìn)一步分析Fragment生命周期:
      1. 執(zhí)行如下代碼栈妆,來加載Fragment時
      fragmentA = new MyFragmentA()
      getSupportFragmentManager().beginTransaction()
                 .add(R.id.frame_root_fragment,fragmentA);///執(zhí)行代碼①
//getSupportFragmentManager().beginTransaction()
      //         .add(R.id.frame_root_fragment,fragmentA).commit();//執(zhí)行代碼②
    得到執(zhí)行Log截圖:
    【執(zhí)行代碼①】
      ![](http://upload-images.jianshu.io/upload_images/2369895-cdbb4fc1f84cda21.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    【執(zhí)行代碼②】
      ![](http://upload-images.jianshu.io/upload_images/2369895-328ad7dcd62a4313.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. 退出Activity操作時
    得到Log截圖:
    ![](http://upload-images.jianshu.io/upload_images/2369895-1f80187dba162619.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  3. Fragment中點(diǎn)擊按鈕執(zhí)行startActivityForResult()方法時
    gif圖:
    ![](http://upload-images.jianshu.io/upload_images/2369895-63ca7a20cd072a89.gif?imageMogr2/auto-orient/strip)
    執(zhí)行**`Fragment.startActivityForResult()`**Log截圖:
    ![](http://upload-images.jianshu.io/upload_images/2369895-4ddaa474719174e5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    執(zhí)行**`getActivity().startActivityForResult()`**Log截圖:
    ![](http://upload-images.jianshu.io/upload_images/2369895-42fc8eb5d94b2464.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 由上可得到</u>***總結(jié)***</u>:
  * new 一個Fragment,F(xiàn)ragment只是調(diào)用了自身的空參數(shù)構(gòu)造方法厢钧,并沒有其他操作鳞尔。
  * Fragment要執(zhí)行其onAttach()及其之后的生命周期方法,需要被FragmentTransition記錄并真正提交到FragmentManager處早直,才能實(shí)現(xiàn)寥假。
  * 如果Fragment要準(zhǔn)備顯示了(即被事務(wù)提交到FragmentManager,具體后面會說到)霞扬,那么它再繼續(xù)執(zhí)行onCreateView()到onResume()的方法糕韧,去創(chuàng)建和綁定UI,最后在前臺顯示喻圃。
  * 由于ViewPager在Activity.onCreate()中并沒有真正初始化界面完成萤彩,即在onCreate()階段中,ViewPager適配器內(nèi)部并沒有真的調(diào)用Fragment的構(gòu)造方法并從FragmentManager中獲取FragmentTransaction事務(wù)來記錄Fragment的操作斧拍,等到Activity.onResume()方法被執(zhí)行(即Activity啟動完成并在前臺顯示了)雀扶,這時,ViewPager才選取默認(rèn)要顯示的那一頁肆汹,并對應(yīng)執(zhí)行這一頁的Fragment的創(chuàng)建+事務(wù)添加+提交給Manager的一個過程愚墓。
 * 在Activity被停止或即將被銷毀的過程中,都首先停止或銷毀它內(nèi)部的所有Fragment昂勉,而它內(nèi)部的所有Fragment則各自檢查自己是否有置于前臺或顯示浪册,如果有,那就得destroyView()銷毀掉它所綁定的View布局并使自己處于完全不可見狀態(tài)岗照,再判斷地執(zhí)行onDestroy()村象。
 * 對于最后一個例子,F(xiàn)ragment執(zhí)行自身的startActivityForResult()和getActivity().startActivityForResult()是有區(qū)別的:如果執(zhí)行自身的startActivityForResult()谴返,那么在另一個Activity返回時煞肾,F(xiàn)ragment就會執(zhí)行自身的onActivityResult()方法,否則嗓袱,只會觸發(fā)Activity的onActivityResult(),除非你在Activity的onActivityResult()方法中添加幾行代碼习绢,讓它把結(jié)果也返回給指定Fragment渠抹,如:
  ```
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (fragmentA!=null)
        fragmentA.onActivityResult(requestCode,resultCode,data);
    
    if (fragmentB!=null)
        fragmentB.onActivityResult(requestCode,resultCode,data);
}
  ```

Fragment開發(fā)遇到的問題和解決(Fragment注意點(diǎn))


一蝙昙、Fragment 與 后臺事務(wù)棧管理

前面說了Fragment的幾個生命周期方法可能不止執(zhí)行一次,關(guān)鍵點(diǎn)就在于Fragment是否被事務(wù)管理到后臺棧中梧却,這里就涉及到與Fragment有關(guān)的幾個類的相關(guān)方法:

  • FragmentTransaction.addToBackStack(String)【關(guān)鍵:讓攜帶著Fragment記錄的事務(wù)保存到后臺棧中】
  • FragmentActivity.onBackPressed()【點(diǎn)擊BACK按鍵或者其他方式觸發(fā)Activity的回退方法時奇颠,會促發(fā)此方法,F(xiàn)ragmentActivity的此方法中會多加一個判斷放航,看后臺棧中是否存在事務(wù)烈拒,存在,則一個事務(wù)出棧广鳍,這個事務(wù)對應(yīng)的Fragment操作記錄則被回退清空荆几,也就是這個事務(wù)下Fragment的操作,全部撤銷赊时,F(xiàn)ragment會從FragmentManager維護(hù)的Fragment隊(duì)列中拿出并被銷毀從而執(zhí)行它的生命周期的余下方法】
  • FragmentManager.popBackStack()【Manager管理的后臺棧的一個出棧操作,返回一個FragmentTransaction事務(wù),但是此操作要等到Application返回它是事件loop時才會觸發(fā)】
  • FragmentManager.popBackStackImmediate()【與popBackStack()方法差不多蛛碌,只是它是立即執(zhí)行出棧操作田轧,而不用顧忌Application】

下面舉個例子,給大家看看Fragment是怎么跑的:
【這里使用FragmentTransaction.replace()作為主要Fragment操作】

原因:
?add()方法與replace()方法大多數(shù)情況下效果是一樣的竭缝,add是指“添加”房维,replace是指“替換”,一般使用同一個FrameLayout去加載Fragment時抬纸,推薦是用replace()的握巢,省去add的多層Fragment重疊,當(dāng)然松却,在需要進(jìn)行輪播等需要及時看到多個Fragment的時候暴浦,add()比較好的。
?remove()晓锻、hide()歌焦、show()、detach()砚哆、attach()等方法独撇,都相應(yīng)地只是執(zhí)行對應(yīng)Fragment的對應(yīng)生命周期方法而已
?所以這里用replace()做演示更好。

主要執(zhí)行的代碼:

  /***
   * 方式一:單個Fragment 做下記錄到backStack
   *
   * @param baseFragment
   */
  public void onAddFragment(Fragment baseFragment) {
      FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
      ft.replace(R.id.frame_root_fragment, baseFragment, "tag");
      ft.addToBackStack("tag");
      ft.commit();
  }

  /**
   * 方式二:多個Fragment同時addToBackStack
   *
   * @param fragmentList
   */
  public void onAddFragments(Fragment[] fragmentList) {
      FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
      int pos = 0;
      for (Fragment item : fragmentList) {
          pos += 1;
          ft.replace(R.id.frame_root_fragment, item, "tag" + pos);
          ft.addToBackStack("tag" + pos);
      }
      ft.commit();
  }

gif圖:

  1. 執(zhí)行方式一代碼(事務(wù)一對一Fragment)
  • Log截圖:


  1. 執(zhí)行方式二代碼(事務(wù)一對多Fragments)
  • Log截圖:



    得出結(jié)論:

    • 從代碼可以看到躁锁,F(xiàn)ragmentTransaction可以記錄一到多個Fragment的相關(guān)操作纷铣。
    • 示例可以知道,F(xiàn)ragmentActivity回退事件發(fā)生時战转,會先把所有的FragmentTransaction事務(wù)一一彈出后臺棧先搜立。【如果一個事務(wù)對應(yīng)一個Fragment槐秧,那么這里就實(shí)現(xiàn)了一個Fragment之間的跳轉(zhuǎn)過程啄踊;而如果一個事務(wù)對應(yīng)多個Fragment忧设,那么,一個事務(wù)彈出颠通,它涉及到的后臺隊(duì)列中Fragment集合便會一下子都彈出銷毀址晕,而不是一個個Fragment地出隊(duì)】

二、Fragment以及它的宿主Activity的復(fù)用

在平時開發(fā)中顿锰,怎么樣方便開發(fā)谨垃、方便維護(hù)、盡量解耦硼控,就怎么寫代碼刘陶,這里給一個比較好的Fragment寫法例子(參考鴻洋博客中的一個Fragment例子),供參考:

  public class ContentFragment extends Fragment  
  {  
      private String mArgument;///Activity傳遞的數(shù)據(jù)(值)
      public static final String ARGUMENT = "argument";///Activity傳遞的數(shù)據(jù)名(鍵)  
      public static final String RESPONSE = "response";///Activity
    
      @Override  
      public void onCreate(Bundle savedInstanceState)  
      {  
          super.onCreate(savedInstanceState);  
          Bundle bundle = getArguments();  
          if (bundle != null)  
          {  
              mArgument = bundle.getString(ARGUMENT);  
              Intent intent = new Intent();  
              intent.putExtra(RESPONSE, "good");  
              getActivity().setResult(ListTitleFragment.REQUEST_DETAIL, intent);  
          }  
    
      }  
      ////在實(shí)例化時獲取Activity傳入的值(這里示例為String類型)
      public static ContentFragment newInstance(String argument)  
      {  
          Bundle bundle = new Bundle();  
          bundle.putString(ARGUMENT, argument);  
          ContentFragment contentFragment = new ContentFragment();  
          contentFragment.setArguments(bundle);  
          return contentFragment;  
      }  
    
      @Override  
      public View onCreateView(LayoutInflater inflater, ViewGroup container,  
              Bundle savedInstanceState)  
      {  
          Random random = new Random();  
          TextView tv = new TextView(getActivity());  
          ///.........
          return tv;  
      }  
  }  

其實(shí)寫法不一淀歇,可能有很多更加靈活的寫法易核,但本文不深究,只要大家有“Fragment的復(fù)用”這個思想浪默,旨在寫出容易復(fù)用牡直、與Activity耦合度小、存在與外界通信接口的Fragment纳决,就能夠?qū)嶋H減少工作量碰逸、理清思路。

下面是一個抽象Activity阔加,用于簡單狀態(tài)Fragment 的Activity自身代碼的復(fù)用饵史,可參考:

public abstract class SingleFragmentActivity extends FragmentActivity  {  
  protected abstract Fragment createFragment();  
  @Override  
  protected void onCreate(Bundle savedInstanceState) {  
      super.onCreate(savedInstanceState);  
      setContentView(R.layout.activity_single_fragment);  
      FragmentManager fm = getSupportFragmentManager();  
      Fragment fragment =fm.findFragmentById(R.id.id_fragment_container);  
      if(fragment == null )  
      {  
          fragment = createFragment() ;  
          fm.beginTransaction().add(R.id.id_fragment_container,fragment).commit();  
      }  
  }  
}  

三、關(guān)于DialogFragment

Android3.0被引入的一類特殊Fragment胜榔,方便我們構(gòu)建具有和Fragment一樣生命周期的一類Dialog等組件胳喷,從而解決普通的Dialog等組件難以管理它的生命周期、與Activity夭织、Fragment交互的限制吭露。詳細(xì)可參考Android 官方推薦 : DialogFragment 創(chuàng)建對話框

四、Fragment與外界的通信

理解了Fragment生命周期和它的基本寫法尊惰,那么讲竿,再說說Fragment與外界的通信。上面提到的DialogFragment就是用于優(yōu)化通信和管理的弄屡,那么题禀,平常我們使用Fragment,應(yīng)該如何保證與其他Fragment和外部Activity進(jìn)行通信呢膀捷?

  1. Fragment與它的宿主Activity通信:
* (Activity傳給Fragment)Activity通過`Fragment.setArguments(Bundle)`在創(chuàng)建Fragment時傳遞數(shù)據(jù)給Fragment迈嘹,在Fragment的onCreate()中,F(xiàn)ragment通過`getArguments()`獲取Bundle數(shù)據(jù)担孔。
* (Activity傳給Fragment)Activity通過`getSupportFragmentManager().findFragmentById()`或`getSupportFragmentManager().findFragmentByTag()`獲取Fragment并調(diào)用Fragment自己定義的方法江锨,數(shù)據(jù)通過參數(shù)形式傳給Fragment吃警。
* (Fragment傳給Activity)Fragment通過`getActivity()`方式獲取宿主Activity糕篇,就可以調(diào)用Activity的方法【但是這樣不嚴(yán)謹(jǐn)啄育,F(xiàn)ragment能夠調(diào)用的方法,應(yīng)該要受到限定拌消,所以挑豌,使用如下代碼的方式,通過在Fragment中定義一個接口墩崩,然后讓宿主Activity實(shí)現(xiàn)這些方法】
  ```

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傳給Fragment氓英、Fragment傳Fragment)還可以通過廣播的方式,讓Fragment去注冊廣播鹦筹,然后铝阐,F(xiàn)ragment調(diào)用`getActivity().sendBroadcast(Intent)`或者Activity調(diào)用`sendBroadcast(Intent)`來發(fā)出廣播,讓注冊了該廣播的Fragment去接收并過濾廣播信息【然而這樣做有些小題大做铐拐,而且需考慮廣播的注冊等】 *<u>關(guān)鍵代碼</u>*:
public class FragmentA extends Fragment{
MyBroadcast broadcast;
//.........
@Override
public View onCreateView(LayoutInflater inflater
, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//........
IntentFilter filter = new IntentFilter();
try {
if (mReceiver != null) {
getActivity().unregisterReceiver(broadcast);
}
} catch (Exception e) {
e.printStackTrace();
}

    broadcast = new MyBroadcast();
    filter.addAction(PageOneFragment.DATA_CHANGED);
    getActivity().registerReceiver(broadcast, filter);

   //........

}
//..................
class MyBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(PageOneFragment.DATA_CHANGED)) {
///徘键。。遍蟋。吹害。。
}
}
}
}
```

  1. Fragment之間的通信:
* 在同一個Activity下的兩個Fragment的通信:FragmentA調(diào)用其宿主Activity的方法虚青,宿主Activity再根據(jù)FragmentA的調(diào)用參數(shù)去調(diào)用FragmentB的方法并傳遞參數(shù)給B它呀。
* 不同Activity下的兩個Fragment的通信:
  * 首先能夠保證兩者都能夠執(zhí)行到onActivityResult()方法【文章前面有說到】
  * (A傳給B)FragmentA通過startActivityForResult()【調(diào)用Fragment本身或者getActivity()都可以】的方式,把Intent數(shù)據(jù)等傳到另一個Activity棒厘,然后讓另一個Activity傳值給FragmentB
  * (B返回給A)FragmentB處理完纵穿,通過getActivity().setResult()把返回的數(shù)據(jù)設(shè)置好,然后返回Activity奢人,A再從它的onActivityResult中拿谓媒。
* 同一個Activity下,DialogFragment 與 Fragment的交互:
  > 原理:FragmentA中new一個DialogFragment對象达传,并讓其`setTargetFragment()`來綁定目的Fragment篙耗,等DialogFragment處理完數(shù)據(jù),調(diào)用剛剛綁定的FragmentA的`onActivityResult()`把數(shù)據(jù)傳回給FragmetnA宪赶。

上關(guān)鍵代碼:

  *<u>Fragment 的代碼</u>*
  ```
public class ContentFragment extends Fragment  
{  
    //...  
    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
            Bundle savedInstanceState)  
    {  
        //....
        tv.setOnClickListener(new OnClickListener()  
        {  
  
            @Override  
            public void onClick(View v)  
            {  
                EvaluateDialog dialog = new EvaluateDialog();  
                //注意setTargetFragment  
                dialog.setTargetFragment(ContentFragment.this, REQUEST_EVALUATE);  
                dialog.show(getFragmentManager(), EVALUATE_DIALOG);  
            }  
        });  
        return tv;  
    }  
  
    //接收返回回來的數(shù)據(jù)  
    @Override  
    public void onActivityResult(int requestCode, int resultCode, Intent data)  
    {  
        super.onActivityResult(requestCode, resultCode, data);  
  
        if (requestCode == REQUEST_EVALUATE)  
        {  
            String evaluate = data  
                    .getStringExtra(EvaluateDialog.RESPONSE_EVALUATE);  
            Toast.makeText(getActivity(), evaluate, Toast.LENGTH_SHORT).show();  
            Intent intent = new Intent();  
            intent.putExtra(RESPONSE, evaluate);  
            getActivity().setResult(Activity.REQUEST_OK, intent);  
        }  
    }  
}  
  ```
 *<u>DialogFragment 的代碼</u>*
    ```

public class EvaluateDialog extends DialogFragment
{
private String[] mEvaluteVals = new String[] { "GOOD", "BAD", "NORMAL" };
public static final String RESPONSE_EVALUATE = "response_evaluate";
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Evaluate :").setItems(mEvaluteVals,
new OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
setResult(which);
}
});
return builder.create();
}
// 設(shè)置返回?cái)?shù)據(jù)
protected void setResult(int which)
{
// 判斷是否設(shè)置了targetFragment
if (getTargetFragment() == null)
return;
Intent intent = new Intent();
intent.putExtra(RESPONSE_EVALUATE, mEvaluteVals[which]);
getTargetFragment().onActivityResult(ContentFragment.REQUEST_EVALUATE,
Activity.RESULT_OK, intent);
}
}
```

補(bǔ)充:關(guān)于DialogFragment調(diào)整窗口大小宗弯,可以參考這篇文章

感謝閱讀


對于Fragment的小小講解,就到此結(jié)束了搂妻,之后會慢慢深入蒙保,謝謝大家支持,喜歡的讀者可以關(guān)注我一波~~

推薦閱讀:
?本人的幾篇文章:
Android開發(fā)細(xì)節(jié)--查漏補(bǔ)缺(二):易忘難懂
Java面試相關(guān)(一)-- Java類加載全過程
?Fragment相關(guān)文章:
http://blog.csdn.net/lmj623565791/article/details/37815413
http://blog.csdn.net/lmj623565791/article/details/42628537/
http://www.cnblogs.com/android-joker/p/4414891.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末欲主,一起剝皮案震驚了整個濱河市邓厕,隨后出現(xiàn)的幾起案子逝嚎,更是在濱河造成了極大的恐慌,老刑警劉巖详恼,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件补君,死亡現(xiàn)場離奇詭異,居然都是意外死亡昧互,警方通過查閱死者的電腦和手機(jī)挽铁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來敞掘,“玉大人叽掘,你說我怎么就攤上這事【裂悖” “怎么了更扁?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長赫冬。 經(jīng)常有香客問我浓镜,道長,這世上最難降的妖魔是什么面殖? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任竖哩,我火速辦了婚禮,結(jié)果婚禮上脊僚,老公的妹妹穿的比我還像新娘相叁。我一直安慰自己,他們只是感情好辽幌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布增淹。 她就那樣靜靜地躺著,像睡著了一般乌企。 火紅的嫁衣襯著肌膚如雪虑润。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天加酵,我揣著相機(jī)與錄音拳喻,去河邊找鬼。 笑死猪腕,一個胖子當(dāng)著我的面吹牛冗澈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播陋葡,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼亚亲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起捌归,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤肛响,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后惜索,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體特笋,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年门扇,在試婚紗的時候發(fā)現(xiàn)自己被綠了雹有。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片偿渡。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡臼寄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出溜宽,到底是詐尸還是另有隱情吉拳,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布适揉,位于F島的核電站留攒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏嫉嘀。R本人自食惡果不足惜炼邀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剪侮。 院中可真熱鬧拭宁,春花似錦、人聲如沸瓣俯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彩匕。三九已至腔剂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驼仪,已是汗流浹背掸犬。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绪爸,地道東北人湾碎。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像毡泻,于是被迫代替她去往敵國和親胜茧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Fragment 描述: ??翻譯可以譯為:碎片、片段,Android 3.0開始引入fragments 的概念呻顽;...
    Lost_Robot閱讀 1,696評論 0 11
  • Fragment廊遍,俗稱碎片嬉愧,自 Android 3.0 開始被引進(jìn)并大量使用。然而就是這樣耳熟能詳?shù)囊粋€東西喉前,在開...
    亦楓閱讀 23,965評論 9 84
  • Fragment是什么 說了半天的Fragment没酣,也看到這么多次Fragment這個名詞出現(xiàn),那么Fragmen...
    October5閱讀 8,256評論 0 8
  • 這篇文章是講有關(guān)于Fragment的使用,大部分還是比較基礎(chǔ)的知識點(diǎn)见咒。之所以寫出來呢偿衰,因?yàn)槲以诠ぷ髦邪l(fā)現(xiàn)在使用fr...
    Haife閱讀 2,410評論 3 12
  • 今天是父親節(jié)。 我懷念我的父親改览。 今天是父親的節(jié)日下翎,可是父親卻離開我們19年了, 我想念我們的父親…… 我懷念父親...
    魯波閱讀 180評論 0 0