Tinker源码分析一:TinkerApplication

1,434 阅读3分钟

自动生成TinkerApplication

接入 Tinker 第一步就是改造 Application 。官方推荐是利用 @DefaultLifeCycle 动态生成 Application

@DefaultLifeCycle(application = "tinker.sample.android.app.SampleApplication",
                  flags = ShareConstants.TINKER_ENABLE_ALL,
                  loadVerifyFlag = false)
public class SampleApplicationLike extends DefaultApplicationLike {
}

那我们来解析一下 Tinker 是如何生成 Application 以及在 Application 中做了什么事?

看到 @DefaultLifeCycle 注解,我们可想而知应该是经过 processor 处理后动态生成了 Application 。

查看 Tinker 工程可以发现在 tinker-android-anno 下面有一个 AnnotationProcessor。

private void processDefaultLifeCycle(Set<? extends Element> elements) {
        // DefaultLifeCycle
        for (Element e : elements) {
            DefaultLifeCycle ca = e.getAnnotation(DefaultLifeCycle.class);

            String lifeCycleClassName = ((TypeElement) e).getQualifiedName().toString();
            String lifeCyclePackageName = lifeCycleClassName.substring(0, lifeCycleClassName.lastIndexOf('.'));
            lifeCycleClassName = lifeCycleClassName.substring(lifeCycleClassName.lastIndexOf('.') + 1);

            String applicationClassName = ca.application();
            if (applicationClassName.startsWith(".")) {
                applicationClassName = lifeCyclePackageName + applicationClassName;
            }
            String applicationPackageName = applicationClassName.substring(0, applicationClassName.lastIndexOf('.'));
            applicationClassName = applicationClassName.substring(applicationClassName.lastIndexOf('.') + 1);

            String loaderClassName = ca.loaderClass();
            if (loaderClassName.startsWith(".")) {
                loaderClassName = lifeCyclePackageName + loaderClassName;
            }

            final InputStream is = AnnotationProcessor.class.getResourceAsStream(APPLICATION_TEMPLATE_PATH);
            final Scanner scanner = new Scanner(is);
            final String template = scanner.useDelimiter("\\A").next();
            final String fileContent = template
                .replaceAll("%PACKAGE%", applicationPackageName) //包名
                .replaceAll("%APPLICATION%", applicationClassName)
                .replaceAll("%APPLICATION_LIFE_CYCLE%", lifeCyclePackageName + "." + lifeCycleClassName)
                .replaceAll("%TINKER_FLAGS%", "" + ca.flags())
                .replaceAll("%TINKER_LOADER_CLASS%", "" + loaderClassName)
                .replaceAll("%TINKER_LOAD_VERIFY_FLAG%", "" + ca.loadVerifyFlag())
                .replaceAll("%TINKER_USE_DLC%", "" + ca.useDelegateLastClassLoader());

            try {
                JavaFileObject fileObject = processingEnv.getFiler().createSourceFile(applicationPackageName + "." + applicationClassName);
                processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Creating " + fileObject.toUri());
                Writer writer = fileObject.openWriter();
                try {
                    PrintWriter pw = new PrintWriter(writer);
                    pw.print(fileContent);
                    pw.flush();

                } finally {
                    writer.close();
                }
            } catch (IOException x) {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, x.toString());
            }
        }
    }

整个 processDefaultLifeCycle 方法看下来,其实主要在做的就是去读取一份模版,然后用注解中设置的值替换里面的一些占位符。这个模版就是 resouces/TinkerAnnoApplication.tmpl

package %PACKAGE%;

import com.tencent.tinker.loader.app.TinkerApplication;

/**
 *
 * Generated application for tinker life cycle
 *
 */
public class %APPLICATION% extends TinkerApplication {

    public %APPLICATION%() {
        super(%TINKER_FLAGS%, "%APPLICATION_LIFE_CYCLE%", "%TINKER_LOADER_CLASS%", %TINKER_LOAD_VERIFY_FLAG%, %TINKER_USE_DLC%);
    }

}

最终生成的 SampleApplication:

public class SampleApplication extends TinkerApplication {

    public SampleApplication() {
        super(15, "tinker.sample.android.app.SampleApplicationLike", "com.tencent.tinker.loader.TinkerLoader", false);
    }

}

解析TinkerApplication

TinkerApplication的构造函数

protected TinkerApplication(int tinkerFlags, String delegateClassName,
                            String loaderClassName, boolean tinkerLoadVerifyFlag) {
    this.tinkerFlags = tinkerFlags;
    this.delegateClassName = delegateClassName; //代理类
    this.loaderClassName = loaderClassName;//
    this.tinkerLoadVerifyFlag = tinkerLoadVerifyFlag;
}

attachBaseContext()

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    final long applicationStartElapsedTime = SystemClock.elapsedRealtime();
    final long applicationStartMillisTime = System.currentTimeMillis();
    Thread.setDefaultUncaughtExceptionHandler(new TinkerUncaughtHandler(this));
    onBaseContextAttached(base, applicationStartElapsedTime, applicationStartMillisTime);
}

onBaseContextAttached()

protected void onBaseContextAttached(Context base, long applicationStartElapsedTime, long applicationStartMillisTime) {
    try {
        loadTinker(); //加载Tinker
        mCurrentClassLoader = base.getClassLoader();//获取ClassLoader
        //创建Handler实例
        mInlineFence = createInlineFence(this, tinkerFlags, delegateClassName,
                tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime,
                tinkerResultIntent);
        //发送消息
        TinkerInlineFenceAction.callOnBaseContextAttached(mInlineFence, base);
        //reset save mode
        if (useSafeMode) {
            ShareTinkerInternals.setSafeModeCount(this, 0);
        }
    } catch (TinkerRuntimeException e) {
        throw e;
    } catch (Throwable thr) {
        throw new TinkerRuntimeException(thr.getMessage(), thr);
    }
}

loadTinker()

private void loadTinker() {
    try {
        //reflect tinker loader, because loaderClass may be define by user!
        //创建TinkerLoader
        Class<?> tinkerLoadClass = Class.forName(loaderClassName, false, TinkerApplication.class.getClassLoader());
        //获取tryLoad方法
        Method loadMethod = tinkerLoadClass.getMethod(TINKER_LOADER_METHOD, TinkerApplication.class);
        Constructor<?> constructor = tinkerLoadClass.getConstructor();
        //执行tryLoad方法
        tinkerResultIntent = (Intent) loadMethod.invoke(constructor.newInstance(), this);
    } catch (Throwable e) {
        //has exception, put exception error code
        tinkerResultIntent = new Intent();
        ShareIntentUtil.setIntentReturnCode(tinkerResultIntent, ShareConstants.ERROR_LOAD_PATCH_UNKNOWN_EXCEPTION);
        tinkerResultIntent.putExtra(INTENT_PATCH_EXCEPTION, e);
    }
}

createInlineFence()

private Handler createInlineFence(Application app,
                                  int tinkerFlags,
                                  String delegateClassName,
                                  boolean tinkerLoadVerifyFlag,
                                  long applicationStartElapsedTime,
                                  long applicationStartMillisTime,
                                  Intent resultIntent) {
    try {
        // Use reflection to create the delegate so it doesn't need to go into the primary dex.
        // And we can also patch it
        //反射获取代理类
        final Class<?> delegateClass = Class.forName(delegateClassName, false, mCurrentClassLoader);
        //获取代理类的构造函数
        final Constructor<?> constructor = delegateClass.getConstructor(Application.class, int.class, boolean.class,
                long.class, long.class, Intent.class);
        //创建代理类实例
        final Object appLike = constructor.newInstance(app, tinkerFlags, tinkerLoadVerifyFlag,
                applicationStartElapsedTime, applicationStartMillisTime, resultIntent);
                
        //反射获取TinkerApplicationInlineFence Class
        final Class<?> inlineFenceClass = Class.forName(
                "com.tencent.tinker.entry.TinkerApplicationInlineFence", false, mCurrentClassLoader);
        //获取ApplicationLike
        final Class<?> appLikeClass = Class.forName(
                "com.tencent.tinker.entry.ApplicationLike", false, mCurrentClassLoader);
        final Constructor<?> inlineFenceCtor = inlineFenceClass.getConstructor(appLikeClass);
        inlineFenceCtor.setAccessible(true);
        //创建TinkerApplicationInlineFence实例
        return (Handler) inlineFenceCtor.newInstance(appLike);
    } catch (Throwable thr) {
        throw new TinkerRuntimeException("createInlineFence failed", thr);
    }
}

TinkerApplicationInlineFence

TinkerApplicationInlineFence继承Handler。TinkerApplication的相应的生命周期会发送消息,然后在handleMessage中调用 ApplicationLike对应的声明周期。

@Keep
public final class TinkerApplicationInlineFence extends Handler {
    private final ApplicationLike mAppLike;

    public TinkerApplicationInlineFence(ApplicationLike appLike) {
        mAppLike = appLike;
    }

    @Override
    public void handleMessage(Message msg) {
        handleMessage_$noinline$(msg);
    }

    private void handleMessage_$noinline$(Message msg) {
        try {
            dummyThrowExceptionMethod();
        } finally {
            handleMessageImpl(msg);
        }
    }

    private void handleMessageImpl(Message msg) {
        switch (msg.what) {
            case ACTION_ON_BASE_CONTEXT_ATTACHED: {
                mAppLike.onBaseContextAttached((Context) msg.obj);
                break;
            }
            case ACTION_ON_CREATE: {
                mAppLike.onCreate();
                break;
            }
            case ACTION_ON_CONFIGURATION_CHANGED: {
                mAppLike.onConfigurationChanged((Configuration) msg.obj);
                break;
            }
            case ACTION_ON_TRIM_MEMORY: {
                mAppLike.onTrimMemory((Integer) msg.obj);
                break;
            }
            case ACTION_ON_LOW_MEMORY: {
                mAppLike.onLowMemory();
                break;
            }
            case ACTION_ON_TERMINATE: {
                mAppLike.onTerminate();
                break;
            }
            case ACTION_GET_CLASSLOADER: {
                msg.obj = mAppLike.getClassLoader((ClassLoader) msg.obj);
                break;
            }
            case ACTION_GET_BASE_CONTEXT: {
                msg.obj = mAppLike.getBaseContext((Context) msg.obj);
                break;
            }
            case ACTION_GET_ASSETS: {
                msg.obj = mAppLike.getAssets((AssetManager) msg.obj);
                break;
            }
            case ACTION_GET_RESOURCES : {
                msg.obj = mAppLike.getResources((Resources) msg.obj);
                break;
            }
            case ACTION_GET_SYSTEM_SERVICE : {
                final Object[] params = (Object[]) msg.obj;
                msg.obj = mAppLike.getSystemService((String) params[0], params[1]);
                break;
            }
            case ACTION_MZ_NIGHTMODE_USE_OF: {
                msg.obj = mAppLike.mzNightModeUseOf();
                break;
            }
            default: {
                throw new IllegalStateException("Should not be here.");
            }
        }
    }

    private static void dummyThrowExceptionMethod() {
        if (TinkerApplicationInlineFence.class.isPrimitive()) {
            throw new RuntimeException();
        }
    }
}

参考

`