Search code examples
androidandroid-serviceandroid-roomdagger-2dagger

Is Dagger AppComponent available even after app get killed


I just started using Dagger library. I've created an AppComponent where I hold a singleton instance of my room database. I have a foreground service which needs to write something to room database when its notification button is clicked. As you know foreground service notification is always visible to user even if the user closes app and I thought if my app gets killed, the AppComponent will no longer be usable. But now I can access it and get the database instance when service notification button is clicked, even if my app has been cleared from recent apps. Here is my code:

Dagger App Module:

@Module
class AppModule {

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

}

Dagger App Component:

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

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

    fun getDatabase(): MyDatabase

}

Application class:

class App : Application() {

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

    companion object {
        lateinit var appComponent: AppComponent
    }
}

Foreground service notification:

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
    }
}

Previous code is working perfectly even if app is completely killed. I just want to now how is it possible for me to access appComponent after app is being killed? Am I using a standard solution? Is anything wrong with my code? Is there a better way to do this?


Solution

  • As EpicPandaForce mentioned in comments, swiping the app away in recents only kills the task, not the application process. Your app process can be killed regardless of whether the task is destroyed. Furthermore, if you have a foreground service running, you know that the app hasn't been destroyed yet.

    This isn't the only reason you can access your Room database.

    If your broadcast receiver is running, then your app has been created

    Suppose you just have a notification without a foreground service. It is possible that your app will be killed in the background, and the notification will still be around. What happens if you click the button on the notification now?

    As stated in the documentation for Application.onCreate():

    Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created.

    Implementations should be as quick as possible (for example using lazy initialization of state) since the time spent in this function directly impacts the performance of starting the first activity, service, or receiver in a process.

    By the time Android instantiates your BroadcastReceiver, the newly recreated application process has already called App.onCreate(), so you will have access to the Room database via a new instance of AppComponent.