Доступен ли компонент приложения Dagger даже после того, как приложение было убито - PullRequest
1 голос
/ 28 мая 2020

Я только начал использовать библиотеку Dagger. Я создал AppComponent, в котором храню одноэлементный экземпляр базы данных моей комнаты. У меня есть служба переднего плана, которой нужно что-то записать в базу данных комнаты при нажатии кнопки уведомления. Как вы знаете, уведомление службы переднего плана всегда видно пользователю, даже если пользователь закрывает приложение, и я подумал, что если мое приложение будет убито, AppComponent больше не будет использоваться. Но теперь я могу получить к нему доступ и получить экземпляр базы данных при нажатии кнопки уведомления службы, даже если мое приложение было удалено из последних приложений. Вот мой код:

Модуль приложения Dagger:

@Module
class AppModule {

    @Provides
    @Singleton
    fun database(context: Context) = Room
         .databaseBuilder(context, MyDatabase::class.java, "my_db.db").build()

}

Компонент приложения Dagger:

@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance context: Context): AppComponent
    }

    fun getDatabase(): MyDatabase

}

Класс приложения:

class App : Application() {

    override fun onCreate() {
        super.onCreate()
        appComponent = DaggerAppComponent.factory().create(applicationContext)
    }

    companion object {
        lateinit var appComponent: AppComponent
    }
}

Передний план служебное уведомление:

val intent = Intent(applicationContext, MyBroadcastReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
    applicationContext,
    0,
    stopIntent,
    PendingIntent.FLAG_UPDATE_CURRENT
)

val notification = NotificationCompat
    .Builder(applicationContext, "channel_id")
    ......
    .addAction(0, "button text", pendingIntent)
    ......
    .build()

BroadcastReceiver:

class MyBroadcastReceiver : BroadcastReceiver() {

    @Inject
    lateinit var database: MyDatabase

    override fun onReceive(context: Context?, intent: Intent?) {
        database = App.appComponent.getDatabase()
        //Write something to database
    }
}

Предыдущий код работает отлично, даже если приложение полностью убито. Я просто хочу теперь узнать, как я могу получить доступ к appComponent после того, как приложение было убито? Я использую стандартное решение? Что-то не так с моим кодом? Есть лучший способ сделать это?

1 Ответ

2 голосов
/ 02 июня 2020

Как упоминалось в комментариях EpicPandaForce, удаление приложения в последних версиях убивает только задачу, но не процесс приложения. Процесс вашего приложения может быть уничтожен независимо от того, уничтожена ли задача. Кроме того, если у вас запущена служба переднего плана, вы знаете, что приложение еще не было уничтожено.

Это не единственная причина, по которой вы можете получить доступ к базе данных Room.

Если ваш широковещательный приемник запущен, значит ваше приложение было создано

Предположим, у вас есть уведомление без службы переднего плана. Вполне возможно, что ваше приложение будет убито в фоновом режиме, но уведомление все равно будет. Что произойдет, если вы сейчас нажмете кнопку в уведомлении?

Как указано в документации для Application.onCreate():

Вызывается при запуске приложения, до создания каких-либо объектов активности, службы или получателя (за исключением поставщиков контента).

Реализации должны выполняться как можно быстрее (например, с использованием отложенной инициализации состояния), поскольку время, проведенное в этой функции, напрямую влияет на производительность запуска первого действия, службы или получателя в процессе.

К моменту, когда Android создает экземпляр BroadcastReceiver, вновь созданный процесс приложения уже вызвал App.onCreate(), поэтому у вас будет доступ к базе данных Room через новый экземпляр AppComponent.

...