1 Activity轉(zhuǎn)Fragment步驟
1.1 基礎步驟
增加Fragment類
根據(jù)Activity增加對應名稱的Fragment類打瘪,實現(xiàn)以下生命周期方法:onCreate() onCreateView() 瑟慈,其中onCreateView返回的view必須是Fragment布局的根視圖分析原Activity
分析Activity是否包含Toolbar屋匕、NavigationView过吻,如果都包含的話新增Fragment繼承AppBarBaseFragment,不包含的話繼承基礎BaseFragment修改Activity的布局
修改Activity的布局要增加的Fragment乳绕,這里使用FrameLayout代替逼纸,后續(xù)通過代碼將Fragment添加到該FrameLayout中定義Fragment的布局
將Activity中布局(包括Toolbar、NavigationView)添加到Fragment中修改Fragment內(nèi)容
先改Fragment類的內(nèi)容菠发,修改中常遇到的問題可以參考下一節(jié)滓鸠,更改完成無任何報錯后第喳,再刪除Activity的內(nèi)容,這樣的方式可以避免修改有遺漏的地方單元測試兼容
編譯AndroidTest APK悠抹,確保自動化測試是兼容的楔敌,無問題引矩。主工程自檢
主工程APK編譯OK后旺韭,進行測試驗證,確保功能OK
1.2 常見遇到的問題
在Fragment中g(shù)etActivity 空指針的問題
【原因】Fragment已經(jīng)onDetach activity了区端,此時通過getActivity去獲取肯定為空织盼。
【解決方法】在onAttach(Activity activity)時,初始化mContext危虱,mActivity唐全,onDetach時置為nullActivity的onRestoreInstanceState 方法在Fragment中無此方法回調(diào)
【解決方法】在Fragment中onSaveInstanceState保存數(shù)據(jù)邮利、onViewStateRestored恢復數(shù)據(jù)Toolbar控件初始化問題
【原則】Toolbar屬于Activity的應用欄, 目前Toolbar加載的NavigationView內(nèi)容都是跟Fragment關聯(lián)的,如果在Activity中初始化Toolbar剪勿,則Fragment中需要指定Activity來拿取Toolbar厕吉,這樣耦合性太強械念,極不合理。綜合考慮Toolbar放在Fragment中進行初始化髓窜。配置應用工具欄時欺殿,在Fragment中通過AppCompatActivity獲取到ActionBar設置ToolbarNavigationView初始化加載布局問題
【原則】NavigationView被Toolbar加載脖苏,同時加載菜單項,這里需要放在Fragment中進行初始化恃鞋。Fragment中Navigation需要被操作隱藏以及加載自定義的布局,放在Activity中無法直接拿到變量畅哑,不便于被替換操作水由。ListView初始化問題
【原則】原來mListView是放在BaseActivity中進行的初始化,仔細查看可知BaseAcitivity中僅僅進行了初始化泥张,無更多邏輯媚创,這里不建議放在BaseActivity中彤恶,只有一行代碼粤剧,單獨拎出來即可。狀態(tài)欄回頂問題
【原則】狀態(tài)欄回頂調(diào)用時焕议,需要傳入ListView盅安,而ListView在Fragment中世囊,故此處狀態(tài)欄回頂只能放在Fragment中進行監(jiān)聽onCreateDialog問題
【原則】簡單改為showDialog,顯示出Dialog即可onNewIntent問題處理
【原則】onNewIntent是Activity中的方法蝙寨,原來的實現(xiàn)可以改為通過Fragment對象來調(diào)用NavigationView Toolbar初始化
【解決】放在基類初始化
2 架構(gòu)指南
2.1 移動應用用戶體驗
請注意墙歪,移動設備的資源也很有限贝奇,因此操作系統(tǒng)可能會隨時終止某些應用進程掉瞳,以便為新的進程騰出空間浪漠。
鑒于這種環(huán)境條件霎褐,您的應用組件可以不按順序地單獨啟動,并且操作系統(tǒng)或用戶可以隨時銷毀它們瘩欺。由于這些事件不受您的控制拌牲,因此您不應在應用組件中存儲任何應用數(shù)據(jù)或狀態(tài),并且應用組件不應相互依賴拍埠。
2.2 常見的架構(gòu)原則
如果您不應使用應用組件存儲應用數(shù)據(jù)和狀態(tài)枣购,那么您應該如何設計應用呢?
分離關注點
要遵循的最重要的原則是分離關注點棉圈。一種常見的錯誤是在一個 Activity 或Fragment 中編寫所有代碼分瘾。這些基于界面的類應僅包含處理界面和操作系統(tǒng)交互的邏輯吁系。您應使這些類盡可能保持精簡汽纤,這樣可以避免許多與生命周期相關的問題。
請注意蕴坪,您并非擁有 Activity 和Fragment 的實現(xiàn)背传;它們只是表示 Android 操作系統(tǒng)與應用之間關系的粘合類。操作系統(tǒng)可能會根據(jù)用戶互動或因內(nèi)存不足等系統(tǒng)條件隨時銷毀它們栋烤。為了提供令人滿意的用戶體驗和更易于管理的應用維護體驗挺狰,您最好盡量減少對它們的依賴买窟。
通過模型****驅(qū)動界面
另一個重要原則是您應該通過模型驅(qū)動界面(最好是持久性模型)始绍。模型是負責處理應用數(shù)據(jù)的組件亏推。它們獨立于應用中的 View 對象和應用組件年堆,因此不受應用的生命周期以及相關的關注點的影響。
持久性是理想之選芽狗,原因如下:
- 如果 Android 操作系統(tǒng)銷毀應用以釋放資源童擎,用戶不會丟失數(shù)據(jù)。
- 當網(wǎng)絡連接不穩(wěn)定或不可用時顾复,應用會繼續(xù)工作芯砸。
應用所基于的模型類應明確定義數(shù)據(jù)管理職責乙嘀,這樣將使應用更可測試且更一致破喻。
2.3 推薦應用架構(gòu)
3 屏幕兼容性
屏幕尺寸是系統(tǒng)為您的應用界面所提供的可見空間。 應用的屏幕尺寸并非設備的實際屏幕尺寸婴噩,而是綜合考慮屏幕方向羽德、系統(tǒng)裝飾(如導航欄)和窗口配置更改(例如宅静,當用戶啟用多窗口模式時)后的尺寸。
3.1 支持不同的屏幕尺寸
使用ConstraintLayout
如需創(chuàng)建適用于不同屏幕尺寸的自適應布局纤垂,最佳做法是將 ConstraintLayout 用作界面中的基本布局。使用ConstraintLayout贾虽,您可以根據(jù)布局中視圖之間的空間關系指定每個視圖的位置和大小。通過這種方式蓬豁,當屏幕尺寸改變時菇肃,所有視圖都可以一起移動和拉伸巷送。
如需使用 ConstraintLayout 構(gòu)建布局矛辕,最簡單的方法是使用 Android Studio 中的布局編輯器。借助該工具飞蹂,您可以將新視圖拖動到布局中陈哑,將其約束條件附加到父視圖和其他同級視圖以及修改視圖的屬性伸眶,完全不必手動修改任何 XML。
如果您使用的是 LinearLayout界酒,則也可以按布局權(quán)重展開子視圖毁欣,以便每個視圖按自身權(quán)重值所占的比例填充剩余的空間岳掐。但是,在嵌套的 LinearLayout 中使用權(quán)重將要求系統(tǒng)執(zhí)行多次布局遍歷以確定每個視圖的尺寸执解,這會降低界面性能衰腌。幸運的是,ConstraintLayout 幾乎能夠構(gòu)建 LinearLayout 所能構(gòu)建的所有布局栅葡,而不會影響性能欣簇,因此您應該嘗試將布局轉(zhuǎn)換為 ConstraintLayout坯约。
使用Fragment將界面組件模塊化
在針對多種屏幕尺寸設計應用時闹丐,您希望確保不會在 Activity 之間不必要地重復界面行為。因此衫仑,您應該使用Fragment 將界面邏輯提取到單獨的組件中堕花。然后缘挽,您可以組合 Fragment 以便在大屏幕設備上運行時創(chuàng)建多窗格布局,或者在手機上運行時將 Fragment 放置在單獨的 Activity 中苏研。
例如,平板電腦上的一款新聞應用可能在左側(cè)顯示報道列表摹蘑,而在右側(cè)顯示一篇完整的報道纹蝴。在左側(cè)選擇一篇報道時塘安,會更新右側(cè)的報道視圖援奢。但是,在手機上砸脊,這兩個組件應顯示在單獨的屏幕上凌埂。從列表中選擇一篇報道時诗芜,會改變整個屏幕以顯示這篇報道瞳抓。
生命周期感知型組件的最佳做法
使界面控制器(Activity 和 Fragment)盡可能保持精簡。它們不應試圖獲取自己的數(shù)據(jù)伏恐,而應使用ViewModel 執(zhí)行此操作孩哑,并觀察LiveData 對象以將更改體現(xiàn)到視圖中。
設法編寫數(shù)據(jù)驅(qū)動型界面翠桦,對于此類界面横蜒,界面控制器的責任是隨著數(shù)據(jù)更改而更新視圖,或者將用戶操作通知給 ViewModel销凑。
將數(shù)據(jù)邏輯放在 ViewModel 類中丛晌。ViewModel 應充當界面控制器與應用其余部分之間的連接器。不過要注意闻鉴,ViewModel 不負責獲取數(shù)據(jù)(例如茵乱,從網(wǎng)絡獲取)孟岛。ViewModel 應調(diào)用相應的組件來獲取數(shù)據(jù),然后將結(jié)果提供給界面控制器次询。
使用 Data Binding 在視圖與界面控制器之間維持干凈的接口。這樣一來,您可以使視圖更具聲明性蔽介,并盡量減少需要在 Activity 和 Fragment 中編寫的更新代碼犀呼。如果您更愿意使用 Java 編程語言執(zhí)行此操作,請使用諸如Butter Knife 之類的庫,以避免樣板代碼并實現(xiàn)更好的抽象化跃须。
如果界面很復雜,不妨考慮創(chuàng)建 presenter 類來處理界面的修改。這可能是一項艱巨的任務娇掏,但這樣做可使界面組件更易于測試。
避免在 ViewModel 中引用View 或Activity 上下文。如果 ViewModel 存在的時間比 Activity 更長(在配置更改的情況下)番电,Activity 將泄露并且不會由垃圾回收器妥善處置婉烟。
使用 Kotlin 協(xié)程管理長時間運行的任務和其他可以異步運行的操作撞牢。