【问题标题】:Flushing RxJava buffer on application close在应用程序关闭时刷新 RxJava 缓冲区
【发布时间】:2021-03-04 05:47:28
【问题描述】:

使用 Timber,我编写了一个 FileTree 记录器,它将 Android 日志写入磁盘上的文件。我缓冲日志,每 2 分钟刷新到磁盘,或 100 条日志消息,以先到者为准。缓冲区防止每条日志消息触发 IO 写入,以免立即写入每条日志消息而导致 IO 资源过载。

我正在使用RxJava 来处理此任务。一个简短的 sn-p(取自 here):

logBuffer.observeOn(Schedulers.computation())
    .doOnEach((log) -> {
        processed++;

        if(processed % 100 == 0) {
            flush();
        }
    })
    .buffer(flush.mergeWith(Observable.interval(2, TimeUnit.MINUTES)))
    .subscribeOn(Schedulers.io())
    .subscribe((logs) -> {
        // Flush the logs to the file
        try {
            File logFile = new File(logDir, "app.log");

            FileWriter fw = new FileWriter(logFile, true);

            for(LogMessage msg : logs) {
                fw.append(msg.toString());
            }

            fw.flush();

            flushCompleted.onNext(logFile.length());
        } catch(Exception e) {
            Timber.e(e, "Failed to flush logs");
        }
    });        

如果我需要手动触发刷新,我会使用“刷新”主题。 我将FileTree 种植在ApplicationonCreate() 内的Timber 中:

public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        Timber.plant(new Timber.DebugTree(), new FileTree(getApplicationContext()));
    }
}

这也是设置RxJava 订阅的地方。我对此有两个问题:

  • 如果应用程序由于某种原因关闭,可能日志刷新不会被计时器触发或接收到足够多的日志消息。我是否应该在每个 ActivityonDestroy() 函数中手动调用flush?有没有更好的方法来做到这一点?
  • 其次,RxJava 抱怨我忽略了“.subscribe()”的结果,大概是因为我永远不会调用dispose()。我不确定如何处理这种情况。订阅与应用程序本身具有相同的生命周期,因此我不确定在特定的ActivityonDestroy 中删除它是否有意义。此外,我的应用程序有几个入口点(主要活动、后台服务和其他一些)都使用日志记录工具,因此何时取消订阅/处置 RxJava 订阅尚不清楚。我的直觉是我不需要处理它们,因为只要操作系统删除应用程序,它们就会被清除。有什么想法吗?

【问题讨论】:

    标签: android rx-java timber-android


    【解决方案1】:
    1. 除了在每个活动完成时复制该代码之外,您还可以使用 BaseActivity,或使用 Application's 活动状态回调 API (https://developer.android.com/reference/android/app/Application#registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks))。

    我应该注意,为了选择一个生命周期方法来刷新,onPause() 之后的任何方法都不能保证被操作系统调用。如果操作系统需要因为内存不足而终止您的应用程序,则不能保证会调用onDestroy()(而是只会终止您的进程)。

    引用https://developer.android.com/reference/android/app/Activity

    请注意上表中的“Killable”列——对于那些方法 被标记为可杀死的,在该方法返回之后 托管活动的进程可能随时被系统杀死 没有另一行代码被执行。正因为如此,你 应该使用 onPause() 方法来写入任何持久性数据(例如 用户编辑)到存储



    1. 如果您的代码的“生命周期”与应用程序的相同,则完全可以忽略订阅结果(因为您永远不会处理订阅)。只需确保您没有在该范围内捕获需要较短生命周期的部分(例如,不要在此处保留对活动上下文的引用,否则您会泄漏它)

    【讨论】:

      猜你喜欢
      • 2015-08-10
      • 2023-03-11
      • 2017-02-19
      • 2012-04-12
      • 2018-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多