av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

Android架構進階之深入理解AppStartup原理

前言

Android Startup提供一種在應用啟動時能夠更加簡單、高效的方式來初始化組件。開發(fā)人員可以使用Android Startup來簡化啟動序列,并顯式地設置初始化順序與組件之間的依賴關系;

讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:空間域名、網(wǎng)頁空間、營銷軟件、網(wǎng)站建設、金臺網(wǎng)站維護、網(wǎng)站推廣。

今天我們就來聊聊

一、使用步驟簡單介紹

使用 AndroidX App Startup 來運行所有依賴項的初始化有兩種方式:

自動初始化;

手動初始化(也是延遲初始化);

1、自動初始化

在 build.gradle 文件內添加依賴;

 
 
 
 
  1. implementation "androidx.startup:startup-runtime:1.0.0-alpha01" 

實現(xiàn) Initializer 接口,并重寫兩個方法,來初始化組件;

 
 
 
 
  1. public class MvpInitializer implements Initializer { 
  2.     @NonNull 
  3.     @Override 
  4.     public Void create(@NonNull Context context) { 
  5.          MvpManager.init(context); 
  6.          return null; 
  7.     } 
  8.     @NonNull 
  9.     @Override 
  10.     public List>> dependencies() { 
  11.         return new ArrayList<>(); 
  12.     } 
  13.     ...... 

create(Context): 這里進行組件初始化工作;

dependencies(): 返回需要初始化的列表,同時設置 App 啟動時依賴庫運行的順序;

在 AndroidManifest.xml 文件中注冊 InitializationProvider;

 
 
 
 
  1.  
  2.         
  3.             android:authorities="${applicationId}.androidx-startup" 
  4.             android:name="androidx.startup.InitializationProvider" 
  5.             android:exported="false" 
  6.             tools:node="merge" > 
  7.            
  8.              
  9.      
  10.  

App 啟動的時 App Startup 會讀取 AndroidManifest.xml 文件里面的 InitializationProvider 下面的 聲明要初始化的組件,完成自動初始化工作;

2、手動初始化(也是延遲初始化)

在 build.gradle 文件內添加依賴;

創(chuàng)建一個類 LibaryD 實現(xiàn) Initializer 接口,并重寫兩個方法,來初始化組件;

在 AndroidManifest.xml 文件中注冊 InitializationProvider

 
 
 
 
  1.  
  2.         
  3.             android:name="androidx.startup.InitializationProvider" 
  4.             android:authorities="${applicationId}.androidx-startup" 
  5.             android:exported="false" 
  6.             tools:node="merge"> 
  7.              
  8.             
  9.                 android:name="com.test.Initializer" 
  10.                 android:value="androidx.startup" 
  11.                 tools:node="remove" /> 
  12.          
  13.      

  • 只需要在 標簽內添加 tools:node="remove" 清單合并工具會將它從清單文件中刪除;
  • 在需要的地方進行初始化,調用以下代碼進行初始化;
  • Initializer.getInstance(context).initializeComponent(Initializer::class.java);
  • 如果組件初始化之后,再次調用 AppInitializer.initializeComponent() 方法不會再次初始化;
  • 手動初始化(也是延遲初始化)是非常有用的,組件不需要在 App 啟動時運行,只需要在需要它地方運行,可以減少 App 的啟動時間,提高啟動速度;

二、源碼分析

1、InitializationProvider

在AndroidManifest文件中配置的組件名必須為androidx.startup.InitializationProvider,現(xiàn)在我們來看這個類的源碼;

 
 
 
 
  1. InitializationProvider.java 
  2. public final class InitializationProvider extends ContentProvider { 
  3.     @Override 
  4.     public boolean onCreate() { 
  5.         Context context = getContext(); 
  6.         if (context != null) { 
  7.             初始化 
  8.             AppInitializer.getInstance(context).discoverAndInitialize(); 
  9.         } else { 
  10.             throw new StartupException("Context cannot be null"); 
  11.         } 
  12.         return true; 
  13.     } 
  14.     @Override 
  15.     public Cursor query(...) { 
  16.         throw new IllegalStateException("Not allowed."); 
  17.     } 
  18.     @Override 
  19.     public String getType(...) { 
  20.         throw new IllegalStateException("Not allowed."); 
  21.     } 
  22.     @Nullable 
  23.     @Override 
  24.     public Uri insert(...) { 
  25.         throw new IllegalStateException("Not allowed."); 
  26.     } 
  27.     @Override 
  28.     public int delete(...) { 
  29.         throw new IllegalStateException("Not allowed."); 
  30.     } 
  31.     @Override 
  32.     public int update(...) { 
  33.         throw new IllegalStateException("Not allowed."); 
  34.     } 

InitializationProvider其實也是利用了 ContentProvider 的啟動機制,在ContentProvider#onCreate(...)中執(zhí)行初始化;

ContentProvider 的其他方法是沒有意義的,所以都拋出了IllegalStateException;

2、自動初始化分析

App Startup 在 ContentProvider 中調用了AppInitializer#discoverAndInitialize()執(zhí)行自動初始化;

AppInitializer是 App StartUp 框架的核心類,整個 App Startup 框架的代碼其實非常少,其中很大部分核心代碼都在 AppInitializer 類中;

2.1.AppInitializer.java discoverAndInitialize

 
 
 
 
  1. final Set>> mDiscovered; 
  2. void discoverAndInitialize() { 
  3.     獲取 androidx.startup.InitializationProvider 組件信息 
  4.     ComponentName provider = new ComponentName(mContext.getPackageName(), InitializationProvider.class.getName()); 
  5.     ProviderInfo providerInfo = mContext.getPackageManager().getProviderInfo(provider, GET_META_DATA); 
  6.    androidx.startup 字符串 
  7.     String startup = mContext.getString(R.string.androidx_startup); 
  8.    獲取組件信息中的 meta-data 數(shù)據(jù) 
  9.     Bundle metadata = providerInfo.metaData; 
  10.     遍歷 meta-data 數(shù)據(jù) 
  11.     if (metadata != null) { 
  12.         Set> initializing = new HashSet<>(); 
  13.         Set keys = metadata.keySet(); 
  14.         for (String key : keys) { 
  15.             String value = metadata.getString(key, null); 
  16.           判斷 meta-data 數(shù)據(jù)中,value 為 androidx.startup 的鍵值對 
  17.             if (startup.equals(value)) { 
  18.                 Class clazz = Class.forName(key); 
  19.                  檢查指定的類是 Initializer 接口的實現(xiàn)類 
  20.                 if (Initializer.class.isAssignableFrom(clazz)) { 
  21.                     Class> component = (Class>) clazz; 
  22.                     將 Class 添加到 mDiscovered Set 中 
  23.                     mDiscovered.add(component); 
  24.                     初始化此組件 
  25.                     doInitialize(component, initializing); 
  26.                 } 
  27.             } 
  28.         } 
  29.     } 
  30. mDiscovered 用于判斷組件是否已經(jīng)自動啟動 
  31. public boolean isEagerlyInitialized(@NonNull Class> component) { 
  32.     return mDiscovered.contains(component); 
  • 獲取androidx.startup.InitializationProvider組件信息(在各個 Module 中聲明的組件信息,會在manifest merger tool的處理下合并);
  • androidx.startup字符串;
  • 獲取組件信息中的 meta-data 數(shù)據(jù);
  • 遍歷 meta-data 數(shù)據(jù);
  • 判斷 meta-data 數(shù)據(jù)中,value 為 androidx.startup 的鍵值對;
  • 檢查指定的類是 Initializer 接口的實現(xiàn)類;
  • 將 Class 添加到 mDiscovered Set 中,這將用于后續(xù) 判斷組件是否已經(jīng)自動啟動;
  • 初始化此組件;

2.2.AppInitializer.java AppInitializer.java

 
 
 
 
  1. private static final Object sLock = new Object(); 
  2. 緩存每個組件的初始化結果; 
  3. final Map, Object> mInitialized; 
  4. 初始化此組件 
  5.  T doInitialize(Class> component, Set> initializing) { 
  6.     對 sLock 加鎖 
  7.     Object result; 
  8.   判斷 initializing 中存在當前組件,說明存在循環(huán)依賴 
  9.     if (initializing.contains(component)) { 
  10.         String message = String.format("Cannot initialize %s. Cycle detected.", component.getName()); 
  11.         throw new IllegalStateException(message); 
  12.     } 
  13.    檢查當前組件是否已初始化 
  14.     if (!mInitialized.containsKey(component)) { 
  15.         當前組件未初始化 
  16.         記錄正在初始化 
  17.         initializing.add(component); 
  18.         通過反射實例化 Initializer 接口實現(xiàn)類 
  19.         Object instance = component.getDeclaredConstructor().newInstance(); 
  20.         Initializer initializer = (Initializer) instance; 
  21.        遍歷所依賴的組件 
  22.         List>> dependencies = initializer.dependencies(); 
  23.         if (!dependencies.isEmpty()) { 
  24.             for (Class> clazz : dependencies) { 
  25.                 如果所依賴的組件未初始化,遞歸執(zhí)行初始化 
  26.                 if (!mInitialized.containsKey(clazz)) { 
  27.                     doInitialize(clazz, initializing); 注意:這里將 initializing 作為參數(shù)傳入 
  28.                 } 
  29.             } 
  30.         } 
  31.        初始化當前組件 
  32.         result = initializer.create(mContext); 
  33.        移除正在初始化記錄 
  34.         initializing.remove(component); 
  35.         緩存初始化結果 
  36.         mInitialized.put(component, result); 
  37.     } else { 
  38.         當前組件已經(jīng)初始化,直接返回 
  39.         result = mInitialized.get(component); 
  40.     } 
  41.      return (T) result; 
  • 對 sLock 加鎖;
  • 判斷 initializing 中存在當前組件,說明存在循環(huán)依賴(這是因為遞歸初始化所依賴的組件時,會將 initializing 作為參數(shù)傳入,如果 initializing 中存在當前組件,說明依賴關系形成回環(huán),如果不拋出異常,將形成無限遞歸);
  • 檢查當前組件是否已初始化;
  • 記錄正在初始化;
  • 通過反射實例化 Initializer 接口實現(xiàn)類;
  • 遍歷所依賴的組件,如果所依賴的組件未初始化,遞歸調用doInitialize(...)執(zhí)行初始化;
  • 初始化當前組件;
  • 移除正在初始化記錄;
  • 緩存初始化結果;

3、手動初始化源碼分析

手動初始化(懶加載)的源碼分析:

 
 
 
 
  1. AppInitializer.java 
  2. public  T initializeComponent(@NonNull Class> component) { 
  3.     調用 doInitialize(...) 方法: 
  4.     return doInitialize(component, new HashSet>()); 

其實非常簡單,就是調用上一節(jié)的doInitialize(...)執(zhí)行初始化。需要注意的是,這個方法是允許在子線程調用的,換句話說,自動初始化與手動初始化是存在線程同步問題的,那么 App Startup 是如何解決的呢?

前面有一個sLock沒有說嗎?其實它就是用來保證線程同步的鎖:

 
 
 
 
  1.  T doInitialize(Class> component, Set> initializing) { 
  2.    對 sLock 加鎖 
  3.     synchronized (sLock) { 
  4.         ...  
  5.     } 

總結

App Startup 是 Jetpack 的新成員,是為了解決因 App 啟動時運行多個 ContentProvider 會增加 App 的啟動時間的問題;

使用了一個 InitializationProvider 管理多個依賴項,消除了每個庫單獨使用 ContentProvider 成本,減少初始化時間;

App Startup 允許你自定義組件初始化順序;

App Startup 提供了一種延遲初始化組件的方法,減少 App 初始化時間;


網(wǎng)站標題:Android架構進階之深入理解AppStartup原理
鏈接URL:http://uogjgqi.cn/article/djijood.html
掃二維碼與項目經(jīng)理溝通

我們在微信上24小時期待你的聲音

解答本文疑問/技術咨詢/運營咨詢/技術建議/互聯(lián)網(wǎng)交流