前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >非侵入式获取Context进行SDK初始化

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

原创
作者头像
静默加载
修改2020-07-09 14:36:12
1.6K0
修改2020-07-09 14:36:12
举报
文章被收录于专栏:振兴的Android修炼手册
context
context

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

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

代码语言:txt
复制
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源码分析和对比 这篇文章。

代码语言:txt
复制
@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 实现自动启。

代码语言:txt
复制
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://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 的初始化:

代码语言:txt
复制
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,历史解毒 这篇文章。

代码语言:txt
复制
<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 源码:

代码语言:txt
复制
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 会自动添加一下的配置:

代码语言:txt
复制
<provider
		android:name="leakcanary.internal.AppWatcherInstaller$MainProcess"
    android:exported="false"
    android:authorities="com.tzx.androidcode.leakcanary-installer" />

AppWatcherInstaller$MainProcess 源码:

代码语言:txt
复制
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 源码分析

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

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

振兴书城
振兴书城

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 非侵入试获取Context进行SDK初始化
    • picasso 初始化
      • InstantRun
        • Leakcanary
          • App Startup
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档