Android IntentService/Service 到 request/send 数据到 Web 服务并获取 UI 的进度
Android IntentService/Service to request/send data to web service and getting the progress to UI
基本上,在 Android 上,我正在尝试 upload/download 来自 Web 服务的数据,并有一个应该显示进度百分比的进度条。
以下是我实施的方法以及考虑它们的原因:
- 后台选择
IntentService
到运行:
根据 link 我无法使用绑定服务,因为它会在绑定 Activity/Fragment 被销毁时销毁。因此选择 IntentService
而不是 Service
。移过去一次,意图服务在工作线程上工作,所以它要好得多。
- 广播以接收更新:
实施
LocalBroadcastManager
以更新进度条 UI,方法是注册它以收听从上述 IntentService
接收到的广播。
但是使用这种方法,需要解决以下问题:
广播顺序未维护。广播携带upload/download的进度百分比。但是由于没有维护序列,所以我有可能收到过时的更新(例如:我可能会在 40% 之后收到 30%)。我也尝试使用 LocalBroadcastManager
的 sendBroadcastSync
方法,但它不能始终如一地工作 (我对此不太确定)。因此,我尝试通过 Handler
实现 Messenger
但是我知道一旦 UI 被重新创建,该方法将无法重新连接到正在进行的 upload/download (Activitiy/Fragment 被销毁并创建)。基本上,对 Handler
的引用与之前的 activity/fragment 一起丢失,因此消息不会传送到 UI 进行更新。
一段时间以来我一直在努力解决问题,但我无法完成。你的智慧之言会很有帮助。
使用接口怎么样。 UI:在 activity/fragment 创建时获取实例和 setCallback(),服务:获取实例并调用更新(如果不是从主线程调用,则使用处理程序,handler.post(可运行 {...更新...})).
如果要通知多个UI实例,在更新器class中保留一个ArrayList,并将'setCallback'方法修改为'addCallback',并更新每个列表'update'.
中的项目
public class ProgressUpdater {
private static ProgressUpdater sUpdater;
private UpdateCallback mCallback;
public interface UpdateCallback {
public void update(long progress);
}
public void setCallback(UpdateCallback callback) {
mCallback = callback;
}
public void update(long progress) {
if (mCallback != null) {
mCallback.update(progress);
}
}
public static ProgressUpdater getInstance() {
if (null == sUpdater) {
sUpdater = new ProgressUpdater();
}
return sUpdater;
}
private ProgressUpdater() {
}
}
如果您想不断更新您的 ui 那么我们可以从服务启动本地广播管理器并在您的 activity.
中注册您的广播接收器
我会以不同的方式解决这个问题,因为消息的排序可能是各种消息解决方案的问题。
在 30% 事件之后获得 40% 事件并不是真正的问题。 是 的问题是,如果您更新 UI 以反映 30%。
让每个事件(使用 LocalBroadcastManager
作为事件总线时每个 Intent
)都包含时间戳和完成百分比。在您的 UI 中跟踪最后一次看到的事件时间戳。如果您收到的事件早于您最后一次看到的事件时间戳,请忽略该事件。
如果您确定您的百分比是单调递增的——换句话说,没有合法的场景可以让您完成从 40% 下降到 30%——您可以跳过时间戳,只应用新的百分比高于您当前显示的百分比。
基本上,在 Android 上,我正在尝试 upload/download 来自 Web 服务的数据,并有一个应该显示进度百分比的进度条。
以下是我实施的方法以及考虑它们的原因:
- 后台选择
IntentService
到运行: 根据 link 我无法使用绑定服务,因为它会在绑定 Activity/Fragment 被销毁时销毁。因此选择IntentService
而不是Service
。移过去一次,意图服务在工作线程上工作,所以它要好得多。 - 广播以接收更新:
实施
LocalBroadcastManager
以更新进度条 UI,方法是注册它以收听从上述IntentService
接收到的广播。
但是使用这种方法,需要解决以下问题:
广播顺序未维护。广播携带upload/download的进度百分比。但是由于没有维护序列,所以我有可能收到过时的更新(例如:我可能会在 40% 之后收到 30%)。我也尝试使用 LocalBroadcastManager
的 sendBroadcastSync
方法,但它不能始终如一地工作 (我对此不太确定)。因此,我尝试通过 Handler
实现 Messenger
但是我知道一旦 UI 被重新创建,该方法将无法重新连接到正在进行的 upload/download (Activitiy/Fragment 被销毁并创建)。基本上,对 Handler
的引用与之前的 activity/fragment 一起丢失,因此消息不会传送到 UI 进行更新。
一段时间以来我一直在努力解决问题,但我无法完成。你的智慧之言会很有帮助。
使用接口怎么样。 UI:在 activity/fragment 创建时获取实例和 setCallback(),服务:获取实例并调用更新(如果不是从主线程调用,则使用处理程序,handler.post(可运行 {...更新...})).
如果要通知多个UI实例,在更新器class中保留一个ArrayList,并将'setCallback'方法修改为'addCallback',并更新每个列表'update'.
中的项目public class ProgressUpdater {
private static ProgressUpdater sUpdater;
private UpdateCallback mCallback;
public interface UpdateCallback {
public void update(long progress);
}
public void setCallback(UpdateCallback callback) {
mCallback = callback;
}
public void update(long progress) {
if (mCallback != null) {
mCallback.update(progress);
}
}
public static ProgressUpdater getInstance() {
if (null == sUpdater) {
sUpdater = new ProgressUpdater();
}
return sUpdater;
}
private ProgressUpdater() {
}
}
如果您想不断更新您的 ui 那么我们可以从服务启动本地广播管理器并在您的 activity.
中注册您的广播接收器我会以不同的方式解决这个问题,因为消息的排序可能是各种消息解决方案的问题。
在 30% 事件之后获得 40% 事件并不是真正的问题。 是 的问题是,如果您更新 UI 以反映 30%。
让每个事件(使用 LocalBroadcastManager
作为事件总线时每个 Intent
)都包含时间戳和完成百分比。在您的 UI 中跟踪最后一次看到的事件时间戳。如果您收到的事件早于您最后一次看到的事件时间戳,请忽略该事件。
如果您确定您的百分比是单调递增的——换句话说,没有合法的场景可以让您完成从 40% 下降到 30%——您可以跳过时间戳,只应用新的百分比高于您当前显示的百分比。