在应用程序关闭时刷新 RxJava 缓冲区
Flushing RxJava buffer on application close
我使用 Timber 编写了一个 FileTree
记录器,它将 Android 日志写入磁盘上的文件。我缓冲日志,每 2 分钟或 100 条日志消息刷新到磁盘,以先到者为准。缓冲区防止每条日志消息触发 IO 写入,以免因立即写入每条日志消息而使 IO 资源过载。
我正在使用 RxJava
来处理这个任务。一小段(摘自 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");
}
});
如果我需要手动触发同花顺,我会使用“同花顺”主题。
我在 Application
的 onCreate()
:
中种植 FileTree
in Timber
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
Timber.plant(new Timber.DebugTree(), new FileTree(getApplicationContext()));
}
}
这也是设置 RxJava
订阅的地方。我有两个问题:
- 如果应用程序由于某种原因关闭,可能不会由计时器或接收到足够的日志消息来触发日志刷新。我应该简单地在 every
Activity
的 onDestroy()
函数中手动调用 flush 吗?有更好的方法吗?
- 其次,
RxJava
抱怨我忽略了“.subscribe()”的结果,大概是因为我永远不会对其调用 dispose()
。我不确定如何处理这种情况。订阅与应用程序本身具有相同的生命周期,因此我不确定在特定 Activity
的 onDestroy
中删除它是否有意义。此外,我的应用程序有几个入口点(主要 activity、后台服务和其他一些)都使用日志记录工具,所以什么时候 unsubscribe/dispose RxJava
订阅不清楚。我的直觉是我不需要处理它们,因为只要应用程序被操作系统删除,它们就会被清除。有什么想法吗?
- 无需在每个 activity 完成时复制该代码,您可以使用
BaseActivity
,或使用 Application's
activity 状态回调 API ( https://developer.android.com/reference/android/app/Application#registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks) ).
我应该注意,为了选择要刷新的生命周期方法,onPause()
之后的任何方法都不能保证被 OS 调用。如果操作系统需要为低内存终止您的应用程序,则不能保证 onDestroy()
会被调用(而是它只会终止您的进程)。
引用https://developer.android.com/reference/android/app/Activity :
Note the "Killable" column in the above table -- for those methods
that are marked as being killable, after that method returns the
process hosting the activity may be killed by the system at any time
without another line of its code being executed. Because of this, you
should use the onPause() method to write any persistent data (such as
user edits) to storage
- 如果您的代码 'lifecycle' 与应用程序的代码相同,则完全可以忽略订阅结果(因为您永远不会处理订阅)。只要确保你没有在那个范围内捕获需要更短生命周期的部分(例如,不要在那里保留对 activity 上下文的引用,否则你会泄漏它)
我使用 Timber 编写了一个 FileTree
记录器,它将 Android 日志写入磁盘上的文件。我缓冲日志,每 2 分钟或 100 条日志消息刷新到磁盘,以先到者为准。缓冲区防止每条日志消息触发 IO 写入,以免因立即写入每条日志消息而使 IO 资源过载。
我正在使用 RxJava
来处理这个任务。一小段(摘自 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");
}
});
如果我需要手动触发同花顺,我会使用“同花顺”主题。
我在 Application
的 onCreate()
:
FileTree
in Timber
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
Timber.plant(new Timber.DebugTree(), new FileTree(getApplicationContext()));
}
}
这也是设置 RxJava
订阅的地方。我有两个问题:
- 如果应用程序由于某种原因关闭,可能不会由计时器或接收到足够的日志消息来触发日志刷新。我应该简单地在 every
Activity
的onDestroy()
函数中手动调用 flush 吗?有更好的方法吗? - 其次,
RxJava
抱怨我忽略了“.subscribe()”的结果,大概是因为我永远不会对其调用dispose()
。我不确定如何处理这种情况。订阅与应用程序本身具有相同的生命周期,因此我不确定在特定Activity
的onDestroy
中删除它是否有意义。此外,我的应用程序有几个入口点(主要 activity、后台服务和其他一些)都使用日志记录工具,所以什么时候 unsubscribe/disposeRxJava
订阅不清楚。我的直觉是我不需要处理它们,因为只要应用程序被操作系统删除,它们就会被清除。有什么想法吗?
- 无需在每个 activity 完成时复制该代码,您可以使用
BaseActivity
,或使用Application's
activity 状态回调 API ( https://developer.android.com/reference/android/app/Application#registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks) ).
我应该注意,为了选择要刷新的生命周期方法,onPause()
之后的任何方法都不能保证被 OS 调用。如果操作系统需要为低内存终止您的应用程序,则不能保证 onDestroy()
会被调用(而是它只会终止您的进程)。
引用https://developer.android.com/reference/android/app/Activity :
Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may be killed by the system at any time without another line of its code being executed. Because of this, you should use the onPause() method to write any persistent data (such as user edits) to storage
- 如果您的代码 'lifecycle' 与应用程序的代码相同,则完全可以忽略订阅结果(因为您永远不会处理订阅)。只要确保你没有在那个范围内捕获需要更短生命周期的部分(例如,不要在那里保留对 activity 上下文的引用,否则你会泄漏它)