android开发分享非侵入式获取Context进行SDK初始化

文章目录非侵入试获取Context进行SDK初始化picasso 初始化InstantRunLeakcanaryApp Startup非侵入试获取Context进行SDK初始化当我们在使用第三方SDK,或者自己进行SDK封装时,如果需要需要用到 Context 进行初始化时,一般做法就是将初始化方法暴露给调用方,让调用方在初始化SDK时,传入上下文环境。publi class App extends Application { @Override public void onCrea.

非侵入式获取Context进行SDK初始化

文章目录

  • 非侵入试获取Context进行SDK初始化
    • picasso 初始化
    • InstantRun
    • Leakcanary
    • App Startup

非侵入试获取Context进行SDK初始化

当我们在使用第三方SDK,或者自己进行SDK封装时,如果需要需要用到 Context 进行初始化时,一般做法就是将初始化方法暴露给调用方,让调用方在初始化SDK时,传入上下文环境。

publi class App extends Application {     @Override     public void onCreate() {         super.onCreate();         MultiDex.install(getApplication());         if (Config.Debug)) {             ARouter.openLog();             ARouter.openDebug();         }         ARouter.init(this);         SkinSdk.init(this);         PaySDK.install(this);         /***部分代码省略***/     } } 

以上的 SDK 初始化代码是不是感觉很难维护。有没有一种直接拿来用而不需要进行 显式 初始化的SDK集成方式呢?

我们知道 ContentProvider 的生命周期,它是在 Application.attach 之后 Application.onCreate 之前进行 installProvider 。不需要我们 显式 通过代码启动。、

所以他满足了我们一般初始化 SDK 的条件:

  • 拥有 Context[Application] 的上下文环境;
  • 可以进行自动启动;

如果大家平时注意观察会发现我们平时使用的一些SDK也是不需要显示初始化的,而他们都是使用自定义的 ContentProvider 这种方式。

picasso 初始化

相关知识可以阅读 Picasso源码分析和对比 这篇文章。

@RestrictTo(LIBRARY) public final class PicassoProvider extends ContentProvider {   @SuppressLint("StaticFieldLeak") static Context context;   @Override public boolean onCreate() {     context = getContext();     return true;   }   /***部分代码省略***/ } 

无侵入试的 Context 获取,依靠 ContentProvider 通过注册在 AndroidManifest.xml 实现自动启。

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="https://schemas.android.com/apk/res/android"     package="com.squareup.picasso" >     <uses-sdk android:minSdkVersion="14" />     <application>         <provider             android:name="com.squareup.picasso.PicassoProvider"             android:authorities="${applicationId}.com.squareup.picasso"             android:exported="false" />     </application> </manifest> 

picasso 的初始化:

public class Picasso {     public static Picasso get() {         if (singleton == null) {             synchronized (Picasso.class) {                 if (singleton == null) {                     if (PicassoProvider.context == null) {                         throw new IllegalStateException("context == null");                     }                     singleton = new Builder(PicassoProvider.context).build();                 }             }         }         return singleton;     } } 

InstantRun

相关知识可以阅读 InstantRun从2.0到3.0,历史解毒 这篇文章。

<application android:theme="@style/AppTheme"               android:label="@string/app_name"               android:icon="@mipmap/ic_launcher"              android:name="com.example.tzx.changeskin.MyApplication"               android:debuggable="true"               android:testOnly="true"               android:allowBackup="true"               android:supportsRtl="true">         <activity android:name="com.example.tzx.changeskin.InstantRunActivity">             <intent-filter>                 <action android:name="android.intent.action.MAIN"/>                 <category android:name="android.intent.category.LAUNCHER"/>             </intent-filter>         </activity>         <provider android:name="com.android.tools.ir.server.InstantRunContentProvider"                   android:multiprocess="true"          android:authorities="com.example.tzx.changeskin.com.android.tools.ir.server.InstantRunContentProvider"/> </application> 

InstantRunContentProvider 源码:

public final class InstantRunContentProvider extends ContentProvider {     public boolean onCreate() {         if (isMainProcess()) {             Log.i(Logging.LOG_TAG, "starting instant run server: is main process");             Server.create(getContext());         } else {             Log.i(Logging.LOG_TAG, "not starting instant run server: not main process");         }         return true;     }     private boolean isMainProcess() {         boolean isMainProcess = false;         if (AppInfo.applicationId == null) {             return false;         }         boolean foundPackage = false;         int pid = Process.myPid();         for (RunningAppProcessInfo processInfo : ((ActivityManager) getContext().getSystemService("activity")).getRunningAppProcesses()) {             if (AppInfo.applicationId.equals(processInfo.processName)) {                 foundPackage = true;                 if (processInfo.pid == pid) {                     isMainProcess = true;                     break;                 }             }         }         if (isMainProcess || foundPackage) {             return isMainProcess;         }         Log.w(Logging.LOG_TAG, "considering this process main process:no process with this package found?!");         return true;     }     /***部分代码省略***/ } 

Leakcanary

进行 LeakCanary 集成的 apk 文件中的 AndroidManifest.xml 会自动添加一下的配置:

<provider 		android:name="leakcanary.internal.AppWatcherInstaller$MainProcess"     android:exported="false"     android:authorities="com.tzx.androidcode.leakcanary-installer" /> 

AppWatcherInstaller$MainProcess 源码:

internal sealed class AppWatcherInstaller : ContentProvider() {   /**    * [MainProcess] automatically sets up the LeakCanary code that runs in the main app process.    */   internal class MainProcess : AppWatcherInstaller()   /**    * When using the `leakcanary-android-process` artifact instead of `leakcanary-android`,    * [LeakCanaryProcess] automatically sets up the LeakCanary code    */   internal class LeakCanaryProcess : AppWatcherInstaller() {     override fun onCreate(): Boolean {       super.onCreate()       AppWatcher.config = AppWatcher.config.copy(enabled = false)       return true     }   }   override fun onCreate(): Boolean {     val application = context!!.applicationContext as Application     InternalAppWatcher.install(application)     return true   }   /***部分代码省略***/ } 

App Startup

Jetpack StartUp官网

我们可以通过使用 ContentProvider 初始化每个依赖关系来满足此需求,但是 ContentProvider 的实例化成本很高,并且可能不必要地减慢启动顺序。此外, ContentProvider 的初始化是无序的。

App Startup 提供了一种更高效的方法,可在应用程序启动时初始化组件并显式定义其依赖关系。

App Startup 源码分析

文章到这里就全部讲述完啦,若有其他需要交流的可以留言哦

想阅读作者的更多文章,可以查看我 个人博客 和公共号:

非侵入式获取Context进行SDK初始化

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/addevelopment/897140.html

(0)
上一篇 2021年10月22日
下一篇 2021年10月22日

精彩推荐