Android開發之奇怪的Fragment

yungfan發表於2016-03-26
說起Android中的Fragment,在使用的時候稍加註意,就會發現存在以下兩種:
  • v4包中的相容Fragment,android.support.v4.app.Fragment
  • 普通的Fragment,android.app.Fragment
這兩種Fragment在使用過程中千萬不要來回串,否則會出現莫名其妙的錯誤

</br>

一、不同版本的使用規則

  • 1、3.0以上:xml中可以直接引用<fragment>,這個是android.app.Fragment,在host Activity中可以使用getFragmentManager()來獲取FragmentManager;

  • 2、3.0以下:

    • 首先libs目錄必須有android-support-v4.jar,能用Fragment全靠它了。
    • 使用的Activity必須繼承自FragmentActivity,使用getSupportFragmentManager獲取FragmentManager;雖然名字一樣但是與高版本匯入的包名不一樣。
    • 不使用佈局檔案的<fragment />標籤,使用其他layout作為容器,然後在程式動態生成。
注意: 這兩個方法都是為了得到FragmentManager,名字一樣但是包名不一樣。

</br>

二、使用Fragment

  • 繼承Fragment類來寫一個Fragment,建立和定義如下:
public class Fragment1 extends Fragment { ... } 
  • Fragment只能存在於Activity中,所以必須要在某處定義它,有兩種方式:
    • 直接在xml佈局檔案中定義;
    • 在xml佈局檔案中定義一個佔位符,然後動態地在Activity中操作Fragment。
注意: Fragment的定義方式會影響它的生命週期,因為在第一種情況下onInflate方法會被呼叫,而第二種情況下它的生命週期是從onAttach方法開始的。

</br>

  • 1、如果在XML檔案中定義Fragment的話,需要:
<fragment android:id="@+id/fragment" 
          class="com.yungfan.fragment.Fragment1" 
          android:layout_width="match_parent" 
          android:layout_height="20dp"/> 
  • 2、如果在XML中用佔位符的話,就不能自由、動態修改Fragment了,此時需要在XML檔案中定義:
<FrameLayout android:id="@+id/fl" 
             android:layout_width="match_parent" 
             android:layout_height="200dp"/> 

然後在Activity裡面手動初始化Fragment,然後把它 “插入”到FrameLayout中。

public class MainActivity extends Activity { 
   
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
   
    Fragment2 f2 = new Fragment2(); 
    FragmentTransaction ft = getFragmentManager().beginTransaction(); 
    ft.replace(R.id.fl, f2); 
    ft.commit(); 
} 

三、Activity獲取Fragment

//3.0以下用 getSupportFragmentManager
FragmentManager fm = getFragmentManager();
//找到對應的fragment
Fragment1 f1 = (Fragment1)fm.findFragmentById(R.id.fragment1);

四、Fragment相互通訊

可以在Fragment1中通過

FragmentManager fm = getActivity().getFragmentManager();
Fragment2 f2 = fm.findFragmentById(R.id.fragment2);

獲取Fragment2,然後可以呼叫Fragment2中的方法

注意:兩個單獨的Fragment之間是不應該進行通訊的,應該使用host Activity來進行通訊。官方推薦做法是:先Fragment1跟它的Activity通訊,可以在Fragment1類中定義一個介面,並在Activity中實現該介面,然後在Activity中與Fragment2通訊。

</br>

五、Fragment中獲取Activity上下文為null的情況

有時候在Fragment呼叫getActivity返回為null,此時可以在Fragment的構造方法中,傳遞一個引數Activity。然後在Activity中new Fragment時將自己傳遞過去即可。

六、Fragment不響應onActivityResult

  • 問題描述:在Fragment中使用startActivityForResult起了一個activity,activity執行完返回結果時,Fragement的onActivityResult卻不會被呼叫。override了host fragment的FragmentActivity的onActivityResult,發現onActivityResult在這裡可以被呼叫到。

  • 原因及解決辦法:返回的result先傳至Fragment的host Activity。這個host Activity的onActivityResult函式必須呼叫super.onActiivtyResult()。super.onActiivtyResult會將未被處理的result訊息繼續傳給其host的fragement的onActiivtyResult。


相關文章