0

In my app, I need to add/remove/update data in my db from a BroadcastReceiver. I am wondering what are the best practices regarding this. Since the onReceive is called on the main thread, I need a way to run the queries on a worker thread and on completion I need the response in the onReceive method.

For this, I used a simple Observer pattern like this.

public class NetworkChangeReceiver extends BroadcastReceiver implements IDbUpdateListener{

    private MyRepository repo;

    private Application application;

    @Override
    public void onReceive(Context context, Intent intent) {
                //Some conditions

                //Initializing and setting listener for repo
                respo = new MyRepository(this); //this is the listener interface

                repo.getAllContents();
            }
        }
    }

    //Interface method implemented
    @Override
    public void onDbUpdate(Content content) {
        //Do something with the data
    }
}

I passed the listener to the repo where I call the onDbUpdate() method on the listener and thereby get the response in the receiver.

If it was an activity/fragment instead of a broadcast receiver, I would have simply used a viewModel with live data as the observable and in my activity, I would observe the viewmodel for changes like this

mViewModel.getAllContent().observe(this, new Observer<List<Content>>() {
   @Override
   public void onChanged(@Nullable final List<Content> contents) {
       // Do something
   }
});

Is my approach ok or is there an obvious better way of achieving this in BroadcastReceiver? Thanks!!

varunkr
  • 5,364
  • 11
  • 50
  • 99
  • Do you need the updates on a view or you need this just to run on the background? And i can also see that you need to run this when there is a network right? – Paul Okeke Sep 13 '18 at 23:50
  • 1
    @PaulOkeke No, I don't need to update any views in this case. I want this to run in the background whenever the corresponding broadcast intent is fired. Yeah, you're right. I need to run this when there is network. Do you have a better approach in mind? The main issue is to get notified once the asynchronous task such as database query or retrofit call finishes. In views this is easily implemented via ViewModel but I was wondering how will a non UI class listen to these events since I beleive using ViewModel with a broadcast receiver is an anti-pattern. – varunkr Sep 14 '18 at 11:11
  • 1
    Please use WorkManager. https://developer.android.com/topic/libraries/architecture/workmanager/basics#recurring. That way you necessarily might not need to listen for network state yourself. WorkMananger can handle that based on the `Constraints` you set for it to run. – Paul Okeke Sep 14 '18 at 11:54
  • @PaulOkeke Looks interesting, I didn't come across this earlier. Will surely read about this. Thanks!! – varunkr Sep 14 '18 at 13:59

1 Answers1

1

I believe you should use some sort of manager that can handle task for you.

Android currently have a library Work Manager that handles this nicely.

With WorkManager you can schedule a OneTimeWorkRequest or a PeriodicWorkRequest.

Another benefit is that you necessarily don't have to listen for connectivity state yourself as you can specify/configure this and a lot others in the constraints passed to WorkManager.

val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .setRequiresDeviceIdle(true)
            .setRequiresCharging(true)
            .build() 

And Yes, it can also handle retries if the network is pretty bad by simply specifying a backOffCriteria.

val workRequest = OneTimeWorkRequest.Builder(RequestWorker::class.java)
            .setInputData(mapOf("record_id" to recordId).toWorkData())
            .setConstraints(constraints)
            .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
            .build()

If you are also interested in the status of the task/work, you can observe LiveData<WorkStatus> by calling getStatusById(workId)

Paul Okeke
  • 1,384
  • 1
  • 13
  • 19