日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Android架構(gòu)進(jìn)階之深入理解AppStartup原理

前言

Android Startup提供一種在應(yīng)用啟動(dòng)時(shí)能夠更加簡(jiǎn)單、高效的方式來(lái)初始化組件。開(kāi)發(fā)人員可以使用Android Startup來(lái)簡(jiǎn)化啟動(dòng)序列,并顯式地設(shè)置初始化順序與組件之間的依賴關(guān)系;

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

今天我們就來(lái)聊聊

一、使用步驟簡(jiǎn)單介紹

使用 AndroidX App Startup 來(lái)運(yùn)行所有依賴項(xiàng)的初始化有兩種方式:

自動(dòng)初始化;

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

1、自動(dòng)初始化

在 build.gradle 文件內(nèi)添加依賴;

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

實(shí)現(xiàn) Initializer 接口,并重寫(xiě)兩個(gè)方法,來(lái)初始化組件;

 
 
 
 
  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): 這里進(jìn)行組件初始化工作;

dependencies(): 返回需要初始化的列表,同時(shí)設(shè)置 App 啟動(dòng)時(shí)依賴庫(kù)運(yùn)行的順序;

在 AndroidManifest.xml 文件中注冊(cè) 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 啟動(dòng)的時(shí) App Startup 會(huì)讀取 AndroidManifest.xml 文件里面的 InitializationProvider 下面的 聲明要初始化的組件,完成自動(dòng)初始化工作;

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

在 build.gradle 文件內(nèi)添加依賴;

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

在 AndroidManifest.xml 文件中注冊(cè) 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.      

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

二、源碼分析

1、InitializationProvider

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

 
 
 
 
  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其實(shí)也是利用了 ContentProvider 的啟動(dòng)機(jī)制,在ContentProvider#onCreate(...)中執(zhí)行初始化;

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

2、自動(dòng)初始化分析

App Startup 在 ContentProvider 中調(diào)用了AppInitializer#discoverAndInitialize()執(zhí)行自動(dòng)初始化;

AppInitializer是 App StartUp 框架的核心類,整個(gè) App Startup 框架的代碼其實(shí)非常少,其中很大部分核心代碼都在 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 的鍵值對(duì) 
  17.             if (startup.equals(value)) { 
  18.                 Class clazz = Class.forName(key); 
  19.                  檢查指定的類是 Initializer 接口的實(shí)現(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)自動(dòng)啟動(dòng) 
  31. public boolean isEagerlyInitialized(@NonNull Class> component) { 
  32.     return mDiscovered.contains(component); 
  • 獲取androidx.startup.InitializationProvider組件信息(在各個(gè) Module 中聲明的組件信息,會(huì)在manifest merger tool的處理下合并);
  • androidx.startup字符串;
  • 獲取組件信息中的 meta-data 數(shù)據(jù);
  • 遍歷 meta-data 數(shù)據(jù);
  • 判斷 meta-data 數(shù)據(jù)中,value 為 androidx.startup 的鍵值對(duì);
  • 檢查指定的類是 Initializer 接口的實(shí)現(xiàn)類;
  • 將 Class 添加到 mDiscovered Set 中,這將用于后續(xù) 判斷組件是否已經(jīng)自動(dòng)啟動(dòng);
  • 初始化此組件;

2.2.AppInitializer.java AppInitializer.java

 
 
 
 
  1. private static final Object sLock = new Object(); 
  2. 緩存每個(gè)組件的初始化結(jié)果; 
  3. final Map, Object> mInitialized; 
  4. 初始化此組件 
  5.  T doInitialize(Class> component, Set> initializing) { 
  6.     對(duì) sLock 加鎖 
  7.     Object result; 
  8.   判斷 initializing 中存在當(dāng)前組件,說(shuō)明存在循環(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.    檢查當(dāng)前組件是否已初始化 
  14.     if (!mInitialized.containsKey(component)) { 
  15.         當(dāng)前組件未初始化 
  16.         記錄正在初始化 
  17.         initializing.add(component); 
  18.         通過(guò)反射實(shí)例化 Initializer 接口實(shí)現(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.        初始化當(dāng)前組件 
  32.         result = initializer.create(mContext); 
  33.        移除正在初始化記錄 
  34.         initializing.remove(component); 
  35.         緩存初始化結(jié)果 
  36.         mInitialized.put(component, result); 
  37.     } else { 
  38.         當(dāng)前組件已經(jīng)初始化,直接返回 
  39.         result = mInitialized.get(component); 
  40.     } 
  41.      return (T) result; 
  • 對(duì) sLock 加鎖;
  • 判斷 initializing 中存在當(dāng)前組件,說(shuō)明存在循環(huán)依賴(這是因?yàn)檫f歸初始化所依賴的組件時(shí),會(huì)將 initializing 作為參數(shù)傳入,如果 initializing 中存在當(dāng)前組件,說(shuō)明依賴關(guān)系形成回環(huán),如果不拋出異常,將形成無(wú)限遞歸);
  • 檢查當(dāng)前組件是否已初始化;
  • 記錄正在初始化;
  • 通過(guò)反射實(shí)例化 Initializer 接口實(shí)現(xiàn)類;
  • 遍歷所依賴的組件,如果所依賴的組件未初始化,遞歸調(diào)用doInitialize(...)執(zhí)行初始化;
  • 初始化當(dāng)前組件;
  • 移除正在初始化記錄;
  • 緩存初始化結(jié)果;

3、手動(dòng)初始化源碼分析

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

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

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

前面有一個(gè)sLock沒(méi)有說(shuō)嗎?其實(shí)它就是用來(lái)保證線程同步的鎖:

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

總結(jié)

App Startup 是 Jetpack 的新成員,是為了解決因 App 啟動(dòng)時(shí)運(yùn)行多個(gè) ContentProvider 會(huì)增加 App 的啟動(dòng)時(shí)間的問(wèn)題;

使用了一個(gè) InitializationProvider 管理多個(gè)依賴項(xiàng),消除了每個(gè)庫(kù)單獨(dú)使用 ContentProvider 成本,減少初始化時(shí)間;

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

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


網(wǎng)站標(biāo)題:Android架構(gòu)進(jìn)階之深入理解AppStartup原理
網(wǎng)站URL:http://m.5511xx.com/article/djijood.html