一.Activity分發:
在Android開發中,Activity是Android的四大組件之一,作爲頁面呈現容器,起到與用戶交互的關鍵功能。一個Activity可以看作一個獨立的容器,可以容納非常多的業務。
Activity的生命週期:
- onCreate():在創建啓動時調用;
- onStart():處於可見狀態時調用;
- onResume():Activity顯示在UI頂層時被調用;
- onPause():Activity不再UI頂層,但依然可見;
- onStop():Activity處於不可見狀態時調用;
- onDetroy():當Activity推出時調用。
Activity的不同聲明週期流程:
- 正常的流程週期:
啓動:Activity:onCreate()->onStart()->onResume();
銷燬:Activity:onPause()->onStop()->onDetroy()。
- 當Activity被其他Activity覆蓋了一部分,或者手機被鎖屏時,會被判定爲可見狀態,但不在UI頂層時,會調用onPause函數。當覆蓋部分被去除或者屏幕解鎖後,AMS會調用該Activity的onResume方式來再次進入運行狀態;
- 當Activity跳轉到新的Activity或按Home鍵回到主屏時,會被壓棧,處於不可見狀態,會調用onPause()->onStop()。當返回上一個Activity時,系統會調用onRestart()->onStart()->onResume()再次進入運行狀態。
- 當Activity處於被覆蓋狀態或後臺不可見狀態時,當更高優先級的app需要內存且系統內存不足時被殺死次Activity。當用戶退回當前Activity時,會調用onCreate()->onStart()->onResume()進入運行狀態。
- 當使用Back鍵退出Activity時,系統會調用onPause()->onStop()->onDetroy()。
按照業務劃分,如activity負責一個整體的大業務,其中有存在很多小業務,那麼此activity就可以被分解爲不同的module來進行管理,需要關注以下規則:
- 大業務中創建小業務的實體。從module層級來說,大業務需要依賴小業務。大業務將創建出小業務的實體;
- 小業務的生命週期擁有其自身的生命週期。小業務的生命週期需嵌入大業務生命週期中進行傳遞,但小業務也需要適當調整和管理自身生命週期中的調用規則;
- 小業務的生命週期不應該超過大業務。小業務的生命週期超過大業務的生命週期,將引發內存泄漏;
- 小業務不會依賴於大業務,小業務之間不存在互相依賴。
需要關注分發對象包含的參數:
- (Activity)Context:上下文對象;
- ViewGroup:佈局對象;
- saveInstanceState:保存狀態的對象。
通過ModuleManager管理這些參數的傳遞,以及初始化每個業務模塊,並且分發生命週期到每個業務模塊中。
- 在Base module中使用CWModuleContext來保存Activity分發的三個參數,一個module可以佔用多個不同的ViewGroup,而使用SparseArray來保存整個佈局的ViewGroup列表(所以Android提供了一個SparseArray類來替代HashMap,SparseArray要比 HashMap 節省內存,某些情況下比HashMap性能更好。SparseArrayCompat是SparseArray 的兼容版本,可以在更低版本的Android運行。我們可以把SparseArray 和 SparseArrayCompat理解爲一個東西。):
-
public class CWModuleContext { public Activity mContext; private Bundle saveInstance; private SparseArray<ViewGroup> mViewGroupSparseArray = new SparseArray<>(); }
- ModuleManager管理這些module與activity的關聯信息,最關鍵的是關聯module和activity之間的生命週期:
-
public class ModuleManager { private List<String> module = new ArrayList<>(); //模塊名字 protected ArrayMap<String,CWAbsExModule> allModules = new ArrayMap<>(); public List<String> getModuleName() { return module; } public void moduleConfig(List<String> modules) { //模塊配置信息 this.module = modules; } public CWAbsExModule getModuleByNames(String name){ return allModules.get(name); } public void onResume() { for (CWAbsExModule module : allModules.values()) { if (module != null){ module.onResume(); } } } public void onPause() { for (CWAbsExModule module : allModules.values()) { if (module != null) { module.onPause(); } } } public void onStop() { for (CWAbsExModule module : allModules.values()) { if (module != null) { module.onStop(); } } } public void onConfigurationChanged(Configuration newConfig) { for (CWAbsExModule module : allModules.values()) { if (module != null) { module.onOrientationChanges(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE); } } } public void onDestroy() { for (CWAbsExModule module : allModules.values()) { if (module != null) { module.onDestroy(); } } } }
全部業務模塊的實現都需要繼承CWAbsModule抽象類:
-
public abstract class CWAbsModule { public abstract boolean init(CWModuleContext moduleContext, Bundle extend); public abstract void onSaveIntanceState(Bundle outState); public abstract void onResume(); public abstract void onPause(); public abstract void onStop(); public abstract void onOrientationChanges(boolean isLandscape); public abstract void onDestroy(); }
-
public abstract class CWAbsExModule extends CWAbsModule { }
- 將ModuleManager擴展成一個ActivityModuleMangager類,用於傳遞activity的三個參數:
二.Fragment分發:
fragment是嵌套於activity中的一個非常大的業務,擁有自身獨立的生命週期。不同業務module也能嵌套到fragment。
Fragment的生命週期:
Fragment的生命週期與Activity的生命週期非常類似,Fragment有其他自身獨有的生命週期函數。
Fragment必須依賴一個Activity運行,所以Activity生命週期調用會優化於Fragment,並且Fragment比Activity輕量:
- onAttach是Fragment與Activity建立關聯時被調用的函數,用於獲取Activity傳遞的值;
- onDetach是Fragment與Activity的關聯被取消時調用的函數;
- onCreatView在創建Fragment視圖時調用;
- onActivityCreated在初始化onCreateView方法的視圖後返回時調用;
- onDestroyView視圖被移除時調用;
Fragment視圖的生命週期簡要解析:
- Fragment創建時調用:onAttatch->onCreate->onCreateView->onActivityCteated
- Fragment可見時調用:onStart->onResume
- Fragment進入後臺不可見狀態的時調用:onPause->onStop
- Fragment銷燬時調用:onPause->onStop->onDestryView->onDestroy->onDetach
Fragment可以看作需要依賴Activity而存在的一個大業務,但是系統已經爲其嵌入好了生命週期,並且Fragment擁有自身棧管理的機制。
在onCreateView函數觸發時機是在Fragment佈局初始化完成後,可以在onCreateView中初始化moduleManager:
三.View分發:
View有兩種構造方法被調用的情況:
1.在View創建時調用;2.在layout文件文件加載被調用。
- onFinishInflate:當View及其子View從XML文件中加載完成後會被調用;
- onAttacheToWindow:當前View被附到一個window上時被調用;
- onMeasure:計算當前View的尺寸及其所有子View的尺寸大小時被調用;
- onSizeChanged:當前View的尺寸變化時被調用;
- onLayout:當前View需要爲其子View分配尺寸和位置時被調用;
- onDraw:繪製View呈現的內容時被調用;
- onWindowFocusChanged:當前View的window獲取或者失去焦點被調用;
- onDetachedFromWindow:當前View從一個window上分離時被調用。
View被加載時,根據參數會有三種情況:
- View在Visible(可見)時的調用:onAttatcheWindow->onMeasure->onSizeChange->onLayout->onDraw
- View在InVisible(不可見)時的調用:onAttatcheWindow->onMeasure->onSizeChange->onLayout
- View在Gone(加載)時只調用onAttatcheWindow。
- View被銷燬時調用:onWindowFoncsChanged->onWindowVisibilityChange->onDetachedFromWindow
Activity和View的生命週期的關聯情況:
- Activity在onCreate階段會使用setContetntView將XML佈局文件的控件映射到Activity佈局中,此時View會執行構造方法,完成View會執行構造方法,完成初始化後回調onFinishInflate方法;
- 在調用生命週期onResume之後,View會相應調用onMeasure方法來測量自身大小,如果大小發生變化就繼續調用onSizeChanged,接着通過onLayout計算放置在佈局中的位置,之後調用onDraw來繪製界面,Activity會調用onWindowFocusChanged來改變焦點;
- onPause和onStop會觸發onWindowFoncsChanged,告訴外界Activity已經失去焦點;
- 在Activity銷燬調用onDestroy時,View會從Activity解綁調用onDetachedFromWindow;
- 異常回收Activity的情況下,保存狀態時調用onSaveInstanceState,恢復調用onRestoreInstanceState。View自身也存在這兩個對應的函數;
- View也擁有onConfigurationChange函數,用於出發視圖配置更新,如橫豎屏的轉換。