【问题标题】:How to use Rxjava for long running background task如何使用 Rxjava 进行长时间运行的后台任务
【发布时间】:2019-09-11 04:46:09
【问题描述】:

我正在使用 rxjava 将一些任务上传到服务器,每当任务启动的片段或活动被破坏时,我将处理订阅以避免内存泄漏,但我想要的是即使在片段/活动被破坏后我需要继续任务在后台运行,有什么办法可以实现吗?

例子

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

是否必须始终处置订阅?如果不是什么时候使用 dispose ?

【问题讨论】:

  • 使用前台服务,让用户知道某项任务正在完成。后台服务并不理想,因为大多数 android OEM 会终止您的后台服务。或者,如果长时间运行的任务不是那么长,你可以让内存泄漏发生一段时间(见这里:stackoverflow.com/a/43546277/2235972

标签: android rx-java rx-java2 rx-kotlin2


【解决方案1】:

那么为什么需要一次性用品?

所以如果你有一些像下面这样的可观察的:

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!");
         }
     });

现在,如果您想停止此任务,则只能通过 dispose() 处理它。

如果用户想要处理任何任务,例如:如果用户从屏幕导航或用户按下后退按钮,那么我们必须在那时终止 Web 请求或取消任何任务。使用 Disposable。

如果您必须在后台执行任何任务并且如果片段被破坏而不杀死怎么办?

您可以简单地只编写 subscribe() 方法并忘记任务。

doSomeLongRunningBgTaks()
     .subscribe()

也许它会帮助你。 谢谢

【讨论】:

    【解决方案2】:

    首先,您必须了解现代版本 AndroidOS 的后台任务限制。关于它的所有内容 [链接] (https://developer.android.com/about/versions/oreo/background) 简而言之,如果您的应用不可见或您的应用没有正在运行的前台服务,则无法保证您的后台工作已完成。

    其次,在您的情况下,您需要有一些实体,它与您的片段或活动的任何生命周期无关,并且能够运行后台工作。有几种可能的解决方案

    1)Android服务方式

    创建一个 Intent 服务。这是一个简单的服务,已经实现了具有内部队列的块。每次客户端尝试通过此类服务执行作业时,服务都会在后台队列中执行此类任务。因此,如果您执行两次,该服务将在执行第二个任务之前完成第一个任务。

    导入 android.app.IntentService 导入android.content.Intent

    class MyIntentService : IntentService("My intent service") {
    
      // This method already in another thread (not UI thread)
      override fun onHandleIntent(intent: Intent?) {
        doLongRunningBackgroundJob()
      }
    }
    

    附注不要忘记在 Manifest 文件中注册此类服务。

    2) Android 处理方式

    您可以创建一个带有内部 android 处理程序的类,该处理程序带有准备好的后台循环器。例如:

    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) 纯java方式

    你可以创建一个纯线程的实例,但更可取的是使用Java框架的executors。 对于线程方法:

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

    对于执行者方法:

    import java.util.concurrent.Executors
    
    class MyBackgroundWorker {
    
      private val executor = Executors.newSingleThreadExecutor()
    
      fun executeJobInBackground(job: Runnable) {
        executor.execute(job)
      }
    }
    

    附注不要忘记使用 DI 方法提供依赖项。

    【讨论】:

    • 它是否适用于应用程序,从最近的应用程序中清除(意味着我想在应用程序从堆栈中清除时在后台运行 ForeGround 服务或 Intent 服务)
    【解决方案3】:

    你可以这样使用:

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

    【讨论】:

    • 这不能回答问题
    • @Deepak 这不是我所期待的答案。
    • 您要执行哪种长时间运行的任务?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-14
    • 2014-10-26
    • 2018-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多