Stack
Stack

Reputation: 1264

How to use Rxjava for long running background task

I am using rxjava for some uploading task to server, Whenever task initiated fragment or activity is destroyed i will be disposing the subscription to avoid memory leak, But what i want is even after the fragment/activity destroyed i need to continue the task running in the background, Is there is any way to achieve this ?

Example

doSomeLongRunningBgTaks()
     .subscribe()
     .addTo(compositeDisposal)
override onDestroy(){
  compositeDisposal.clear()
}

Is it mandatory to dispose the subscription all time ? if not when to use dispose ?

Upvotes: 2

Views: 5305

Answers (3)

Mahavir Jain
Mahavir Jain

Reputation: 1581

So Why you need Disposable ?

So if you have some observable like below :

Observable.just("Hello world!")
     .delay(1, TimeUnit.SECONDS)
     .subscribeWith(new DisposableObserver<String>() {
         @Override public void onStart() {
             System.out.println("Start!");
         }
         @Override public void onNext(String t) {
             System.out.println(t);
         }
         @Override public void onError(Throwable t) {
             t.printStackTrace();
         }
         @Override public void onComplete() {
             System.out.println("Done!");
         }
     });

now if you want to stop this task than it is disposed via dispose() only.

Some time if user wants to dispose any task like : If user navigate from screen or user presses back button than we have to terminate the web request or cancel any task at that time Disposable is used.

What if you have to perform any task in background and not kill if fragment is destroyed ?

You can simple write only subscribe() method and forgot the task.

doSomeLongRunningBgTaks()
     .subscribe()

May be it will help you. Thanks

Upvotes: 3

Oleg Kuzmin
Oleg Kuzmin

Reputation: 301

First of all, you have to be aware of background task restriction of modern versions of AndroidOS. All about it here [a link] (https://developer.android.com/about/versions/oreo/background) In short, if your app is not visible or your app doesn't have running foreground service there is not any guarantee that your background work is completed.

Secondly, in your case, you need to have some entity which is not tied to any lifecycle of your fragments or activity and able to run background work. There are several possible solutions

1) Android service way

Create an Intent service. It's a simple service with already implemented blocks which has internal Queue. Every time when a client tries to execute a job through such service, service executes such task in a background queue. So if you executes it twice, the service will wat first task completion before the execution of the second task.

import android.app.IntentService import android.content.Intent

class MyIntentService : IntentService("My intent service") {

  // This method already in another thread (not UI thread)
  override fun onHandleIntent(intent: Intent?) {
    doLongRunningBackgroundJob()
  }
}

P.S. Do not forget to register such service in the Manifest file.

2) Android handler way

You can create a class with an internal android handler with prepared background looper. For example:

import android.os.Handler
import android.os.HandlerThread

class MyBackgroundWorker {

  private val handler = initHandler()

  private fun initHandler(): Handler {
    val handlerThread = HandlerThread("My background thread")
    handlerThread.start()
    return Handler(handlerThread.looper)
  }

  fun executeJobInBackground(job: Runnable) {
    handler.post(job)
  }
}

3) Pure java way

You can create an instance of pure thread, but more preferable to use executors Java framework. For the thread approach:

class MyBackgroundWorker {

  fun executeJobInBackground(job: Runnable) {
    Thread(job).start()
  }
}

For the executor approach:

import java.util.concurrent.Executors

class MyBackgroundWorker {

  private val executor = Executors.newSingleThreadExecutor()

  fun executeJobInBackground(job: Runnable) {
    executor.execute(job)
  }
}

P.S. Do not forget to provide dependencies using DI approach.

Upvotes: 3

Deepak Rajput
Deepak Rajput

Reputation: 761

You can use something like this:

webService.doSomething(someData)
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(
          result -> resultText.setText("It worked!"),
          e -> handleError(e));

Upvotes: -1

Related Questions