JobScheduler JobService запускается без приложения
Недавно мы преобразовали наш основной класс приложений в Kotlin.
С тех пор мы сталкиваемся с авариями, особенно ночью (когда наше приложение, вероятно, было убито системой), когда наш JobService запущен.
Мы обращаемся к контексту приложения статическим образом для некоторых зависимостей, которые работали очень хорошо, прежде чем мы преобразовали класс в Kotlin. С тех пор статический геттер представляет собой lateinit var
который инициализируется в приложении onCreate
.
После релиза Google Play сообщили об этих сбоях:
Caused by: kotlin.UninitializedPropertyAccessException:
at x.y.z.application.App.access$getAppContext$cp
[...]
at x.y.z.jobs.JobSchedulerService.onCreate (JobSchedulerService.java:27)
Что приводит к вопросу, является ли наш Application.onCreate()
не выполненным?
Мы реорганизовали JobService немного, чтобы уменьшить количество статического контекстного доступа до тех пор, пока не понадобится основной рефакторинг. После этого мы получили эти сбои от наших пользователей в Google Play Console:
Caused by: kotlin.UninitializedPropertyAccessException:
at org.koin.standalone.StandAloneContext.getKoinContext (StandAloneContext.java:45)
at org.koin.java.standalone.KoinJavaComponent.get (KoinJavaComponent.java:66)
at org.koin.java.standalone.KoinJavaComponent.get$default (KoinJavaComponent.java:64)
at org.koin.java.standalone.KoinJavaComponent.get (KoinJavaComponent.java)
at x.y.z.SearchState.<init> (SearchState.java:21)
[...]
at x.y.z.jobs.JobSchedulerService.onStartJob (JobSchedulerService.java:54)
Эти сбои говорят нам то же самое: Application.onCreate()
не был выполнен, потому что Koin не инициализирован.
Итак, мой вопрос? Почему при конвертировании в Kotlin или почему наше приложение не создано до того, как JobService будет запущен, время выполнения Application.onCreate()
изменится?
Я имею в виду, конечно, мы могли бы реорганизовать все зависимости приложений для использования контекста, предоставленного самим JobService, но что, если приложение будет создано впоследствии, и мы все еще хотим использовать Koin? Наше приложение, вероятно, снова AlreadyStartetException
с AlreadyStartetException
. И если наше приложение еще не "там", какой контекст будет у службы?
Источники (упрощенные):
заявка
abstract class App : MultiDexApplication() {
companion object {
@JvmStatic
lateinit var appContext: Context
@JvmStatic
val isDevelopment: Boolean = BuildConfig.DEBUG
// @JvmStatic
// val isDevelopment: Boolean by lazy {
// appContext.resources.getBoolean(R.bool.isDevelopment)
// }
}
override fun onCreate() {
super.onCreate()
appContext = applicationContext
startKoin(
applicationContext,
listOf(
coreModule,
sharedPrefsModule
)
)
}
}
JobService
public class JobSchedulerService extends JobService implements OnFinishListener {
@Override
public boolean onStartJob(JobParameters params) {
if (App.isDevelopment()) { //First crash cause 'isDevelopment' relied on App.appContext
...
}
this.mJobParameters = params;
this.mStateMachine = StateContext.getInstance(getApplication());
mStateMachine.setOnFinishListener(this);
mStateMachine.execute("" + params.getJobId()); //Second crash is in the first executed state auf this state Machine
return true;
}
}
Регистрация манифеста
<service
android:name="x.y.z.jobs.JobSchedulerService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE">
</service>
SearchState
public class SearchState extends State {
//Koin Crash in SearchState.<init>
private PlacemarkRepository placemarkRepository = get(PlacemarkRepository.class);
...
}