0

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

RxJava用来处理这个任务。一个简短的片段(取自此处):

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

如果我需要手动触发刷新,我会使用“刷新”主题。我在's内种植FileTreeTimber :ApplicationonCreate()

public class App extends Application {

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

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

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

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

1 回答 1

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. 如果您的代码的“生命周期”与应用程序的相同,则完全可以忽略订阅结果(因为您永远不会处理订阅)。只需确保您没有在该范围内捕获需要较短生命周期的部分(例如,不要在此处保留对活动上下文的引用,否则您将泄漏它)
于 2021-03-03T21:42:05.687 回答