天天看點

Fragment生命周期的坑和DialogFragment寬高的坑

最近在開發單頁面應用,多個fragment嵌套在一個activity裡面,和之前單個Fragment依賴在activivty中管理還是有點不同,我這Fragment嵌套了3層,最終還是出問題了。

一.Fragment生命周期的坑

1.問題描述

我用FragmentManager去管理和切換Fragment,在這過程中用到了回退棧,先聲明對于回退棧的出棧操作

fragmentmanager.popBackStack();
           

在傳回時是會調用Fragment的生命周期onCreateView -> onResume的。是以在這個過程中就出問題了,我在onCreateView中設定

editText.setText("balabalabalala");
           

然後當頁面展示之後,我手動去改成"bilibili",然後跳轉到另一個Fragment,傳回時,原本的Fragment會調用onCreateView方法,這個方法裡有執行了editText.setText("balabalabalala"),是以按理來說最後EditText的輸出應該是balabalabalala,結果卻是bilibili。

2.重制這個問題

因為我用Fragment嵌套加上使用回退棧才出現這個問題,我打算用另一種簡單的形式重制這個問題。假如我有一個ActivityA,它裡面有一個FragmentA,我從ActivityA跳轉到ActivityB再傳回的話是不會重新調用FragmentA的生命周期的,是以自然無法再次重制這個問題。但是我可以使用轉屏來重制這個問題。沒錯,在普通的情況下轉屏也會出現這個問題。因為轉屏會使Activity重新建立,内部的Fragment也會重新建立。

假如你在ActivityA中有個FragmentA,FragmentA中有個EditText,你預設在它的onCreateView方法中去輸入一個字元串,再運作的時候手動去改變這個Edittext的内容,然後轉屏。你會發現雖然調用了onCreateView,但是Edittext的内容還是你之前手動去輸入的内容。

3.解決方法

其實這個就是Fragment生命周期的關系,我們都知道如果Activity被銷毀重建的話,可以在onCreate中拿到savedInstanceState再重新指派,而fragment是在onActivityCreate這個生命周期方法中設定之前的狀态的。還有一點因素是設定了id屬性的控件會自動去加載它之前的資料(TextView除外,如果你用TextView你就會發現它沒法擷取銷毀前的資料,而是重新設值,因為TextView要另外設定一個屬性才能儲存銷毀前的值,這個屬性我忘了是啥了)。

還有一個比較重要的地方,雖然是在onActivityCreate這個地方擷取之前的值,但是如果你在onActivityCreate設定資料的話,還是會被原來的值覆寫。是以至少要在onStart方法中去設定,你可以用上面的案例,把在onCreateView中設值改成在onStart中設值,你會發現Fragment重新建立時會被重新成功設值。

這個問題雖然不是一個很嚴重的問題,但是會很容易被忽略,是以涉及到Fragment被銷毀和重建的地方還是要注意一下。

二.DialogFragment寬高的坑

(1)DialogFragment中的Fragment是可以再show一個DialogFragment的。

(2)如果DialogFragment的Fragment中再嵌套Fragment,父布局可以設定wrap_content随子布局的寬高,這是沒問題。

(3)我的是7.0的系統,DialogFragment自定義布局時設定父布局的寬高會無效,不管怎麼設都是全屏。而父布局設定wrap_content,在父布局中嵌套一層子布局再設具體的寬高就可以正常展示我們想要的結果。

(4)我不知道是不是我自定義DialogFragment的原因,設寬高的話要對嵌套的子布局設才有用,對window設也沒用。是以動态設定布局寬高我是對子布局去設定的,對window設定沒效果。

(5)預設情況下布局會有間距,我照方法對window去消除邊距是沒效果的。按照上面說的對布局才管用,我就嘗試對布局消除邊距,結果還真有效果。

在父布局中加入background,自定義DialogFragment的xml最頂層的布局

android:background="@drawable/ibn_activity_container"
           
Fragment生命周期的坑和DialogFragment寬高的坑

這樣就能消除邊距了。

至于為什麼要在内部布局設才有用,給window設沒用,這個我就不知道了。但是如果你在嘗試給window設定這些沒效果時,你可以對布局去設定。

繼續閱讀