Dagger2 - инъекция в приложение для Android с поддержкой Instant App и динамических модулей - PullRequest
0 голосов
/ 01 ноября 2018

Я пытаюсь настроить шаблонный / проверочный концепт-репозиторий для приложения Android с поддержкой Instant App и Dynamic Module, в то же время внедряя некоторые сторонние библиотеки, такие как Room и Retrofit. Это написано на Kotlin. Код можно найти на GitHub - Stabber .

Я нахожусь на этапе добавления поддержки API SplitCompat, чтобы я мог динамически устанавливать динамические модули, как описано в App Bundle - Руководство по игре на ядре .

В этом руководстве описано, что можно использовать SplitCompatApplication в качестве реализации своего приложения в своем манифесте Android (и здесь я предполагаю, что эта часть входит в манифест базового модуля, из-за модели зависимостей всех модулей, поправьте меня если я ошибаюсь).

Я следовал за разделом, где описывается, что на самом деле делает SplitCompatApplication, и сказано, что он просто переопределяет Application, как указано здесь:

SplitCompatApplication просто переопределяет ContextWrapper.attachBaseContext() для включения SplitCompat.install(Context applicationContext). Если вы не хотите, чтобы ваш класс Application расширял SplitCompatApplication, вы можете переопределить метод attachBaseContext() вручную, как показано ниже:

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    // Emulates installation of future on demand modules using SplitCompat.
    SplitCompat.install(this);
}

Итак, я сделал именно это, но с версией, которая учитывает, что я поддерживаю Instant Apps, поэтому мое тело этой функции переопределено на самом деле:

override fun attachBaseContext(base: Context?) {
    super.attachBaseContext(base)
    val isInstant = InstantApps.isInstantApp(this)
    if (!isInstant) {
        SplitCompat.install(this)
    }
}

Итак, кроме кода, показанного в ранее связанном руководстве, я просто вынимаю чек и сохраняю его в переменной, которая все еще дает тот же результат. Моя проблема в том, что я больше не могу запускать свое приложение, так как оно выдает следующее исключение:

Process: app.instant.stabber.app, PID: 6788
    java.lang.RuntimeException: Unable to instantiate application app.instant.stabber.android.StabberApplication: java.lang.IllegalStateException: Application context is null!
        at android.app.LoadedApk.makeApplication(LoadedApk.java:1017)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5940)
        at android.app.ActivityThread.-wrap1(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1755)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6753)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:482)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
     Caused by: java.lang.IllegalStateException: Application context is null!
        at com.google.android.instantapps.InstantApps.isInstantApp(InstantApps.java:62)
        at app.instant.stabber.android.StabberApplication.attachBaseContext(StabberApplication.kt:30)
        at android.app.Application.attach(Application.java:218)
        at android.app.Instrumentation.newApplication(Instrumentation.java:1107)
        at android.app.Instrumentation.newApplication(Instrumentation.java:1091)

Я даже пытался сделать что-то подобное, чтобы исправить тот факт, что Context (приложение ..?) Кажется пустым:

 override fun attachBaseContext(base: Context?) {
    super.attachBaseContext(base)
    this?.let { me ->
        val isInstant = InstantApps.isInstantApp(me)
        if (!isInstant) {
            SplitCompat.install(me)
        }
    }
}

Я действительно не могу понять, куда идти отсюда, хотя. У кого-нибудь есть идеи, что вызывает это? Единственное, о чем я могу думать, это то, что что-то не так с манифестами, потому что это то, с чем я боролся много раньше. Манифесты и тот факт, что способ обработки ресурсов в этой модульности приложений Android очень странный (некоторые строковые значения, которые мне пришлось поместить в базу вместо мгновенных функций и т. Д.).

РЕДАКТИРОВАТЬ: В текущем коде я не переопределяю его вручную, чтобы приспособить Мгновенные приложения (как предложено в руководстве, которое я связал), и вместо этого я просто подкласс SplitCompatApplication. Кажется, он работает, но я еще не тестировал установку динамических модулей.

РЕДАКТИРОВАТЬ 2: То, что я придумал в конце, но я хочу знать, почему я должен сделать это на первом месте, хотя я следовал точным инструкциям:

override fun attachBaseContext(base: Context?) {
    super.attachBaseContext(base)
    this.applicationContext?.let { _ ->
        val isInstant = InstantApps.isInstantApp(this)
        if (!isInstant) {
            SplitCompat.install(this)
        }
    }
}
...