我正在构建一个健身应用程序,它不断记录设备上的活动.我需要经常登录,但我也不想不必要地耗尽我的用户电池,这就是为什么我在考虑将网络呼叫一起批处理并在无线电处于活动状态时立即将它们全部发送,设备是连接到WiFi或正在充电.
我正在使用基于文件系统的方法来实现它.我首先坚持数据File
- 最终我可能会使用Tape from Square来做到这一点 - 但这是我遇到第一个问题的地方.
我不断写新的日志数据File
,但我还需要定期将所有记录的数据发送到我的后端.当发生这种情况时,我删除了内容File
.现在的问题是如何防止这两种操作同时发生?当然,如果我尝试将日志数据写入到File
其他进程正在读取File
并尝试删除其内容的同时,它将导致问题.
我正在考虑使用一个IntentService
基本上充当所有这些操作的队列.从那以后 - 至少我已经阅读了 - 在单个工作程序中按顺序执行IntentServices
句柄,这些操作中的两个操作不应该同时发生,对吧?Intent
Thread
目前我想安排一个PeriodicTask
将GcmNetworkManager
负责将数据发送到服务器.有没有更好的方法来做这一切?
你的方法比以前更加复杂!由于某种原因,没有其他答案指出这一点,但GcmNetworkManager
已经做了你想要实现的一切!你不需要自己实现任何东西.
您似乎并不知道GcmNetworkManager
已经通过自动重试等以最节省电池的方式批量调用,并且它还可以跨设备启动执行任务,并且可以确保在您的应用程序需要电池效率时尽快执行.
只要您有数据来保存计划,OneOffTask
就像这样:
final OneoffTask task = new OneoffTask.Builder() // The Service which executes the task. .setService(MyTaskService.class) // A tag which identifies the task .setTag(TASK_TAG) // Sets a time frame for the execution of this task in seconds. // This specifically means that the task can either be // executed right now, or must have executed at the lastest in one hour. .setExecutionWindow(0L, 3600L) // Task is persisted on the disk, even across boots .setPersisted(true) // Unmetered connection required for task .setRequiredNetwork(Task.NETWORK_STATE_UNMETERED) // Attach data to the task in the form of a Bundle .setExtras(dataBundle) // If you set this to true and this task already exists // (just depends on the tag set above) then the old task // will be overwritten with this one. .setUpdateCurrent(true) // Sets if this task should only be executed when the device is charging .setRequiresCharging(false) .build(); mGcmNetworkManager.schedule(task);
这将做你想要的一切:
任务将保留在磁盘上
任务将以批量和电池效率的方式执行,最好通过Wifi
您将具有可配置的自动重试,具有电池效率的退避模式
任务将在您指定的时间窗口内执行.
我建议初学者阅读本文以了解更多相关内容GcmNetworkManager
.
你真正需要做的是落实在你的网络调用Service
扩展GcmTaskService
以后每当你需要执行这样的网络呼叫您安排OneOffTask
和其他一切将采取为你照顾!
当然,你不需要打电话给OneOffTask.Builder
我上面这样的每个人- 我只是这样做,向你展示你拥有的所有选项.在大多数情况下,安排任务看起来像这样:
mGcmNetworkManager.schedule(new OneoffTask.Builder() .setService(MyTaskService.class) .setTag(TASK_TAG) .setExecutionWindow(0L, 300L) .setPersisted(true) .setExtras(bundle) .build());
如果你把它放在一个辅助方法中,或者甚至更好地为你需要做的所有不同任务创建工厂方法,那么你应该做的每件事都应该归结为几行代码!
顺便说一下:是的,在一个工人中依次IntentService
处理.您可以在此处查看相关实施.它实际上非常简单而且很直接.Intent
Thread