Search code examples
androidbroadcastreceiverandroid-viewmodel

Android: What is the best way to access ViewModel method from Broadcast receiver?


I have a viewmodel with a method Refresh(), which accesses DB and updates UI. I need to call this method whenever Airplane mode changes. How to do this?

Implementation of Broadcast receiver:

class AirplaneModeChanged() : BroadcastReceiver() {

    override fun onReceive(p0: Context?, p1: Intent?) {
        if (p1?.action?.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED) == true) {
            /* MyViewModel.refresh() */
        }
    }
}

Implementation of Viewmodel:

class MyViewModel(application: Application) : AndroidViewModel(application) {
    fun refresh() 
    { 
        /* Access DB and update UI */ 
    }

}


MainActivity:

class MainActivity : ComponentActivity(), LifecycleOwner {
    private val viewModel: MyViewModel by viewModels()
    private val airplaneModeChanged = AirplaneModeChanged()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ContextCompat.registerReceiver(applicationContext, airplaneModeChanged, IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED),
            ContextCompat.RECEIVER_NOT_EXPORTED)

    }

    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(airplaneModeChanged)
    }
}


Solution

  • The best way is to not try to access your ViewModel from the BroadcastReceiver. Instead, have both of these classes call a third class that does what you want done.

    class MyDataSource { 
        fun fetchData(){}
    }
    

    Then you can do

    class AirplaneModeChanged(val dataSource : MyDataSource) : BroadcastReceiver() {
    
        override fun onReceive(p0: Context?, p1: Intent?) {
            if (p1?.action?.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED) == true) {
                dataSource.fetchData()
            }
        }
    }
    

    and

    class MyViewModel(application: Application, val dataSource : MyDataSource) : AndroidViewModel(application) {
        fun refresh() 
        { 
            dataSource.fetchData()
        }
    
    }