1

我的 Android 应用程序必须:

  • 将图像上传到服务器

  • 使用上传的图像图像对 REST Web 服务进行3 次(快速)调用

  • 从网络服务获取输出

  • 在 ui 上显示输出。

我对应该使用 Service 还是 AsyncTask 感到困惑。

我认为我应该使用 AsyncTask,因为任务需要在后台完成,并且一旦过程完成,结果需要显示在 UI 上。和方法似乎非常适合doInBackground()这类postExecute()事情。

但是,我从 Android 文档和几个 StackOverflow 答案中读到使用服务更合适。问题是我想在任务完成后立即在 UI 上显示输出。如果用户退出应用程序,那么我希望上传停止。

我很困惑:AsyncTask 真的是更好的选择吗?

4

2 回答 2

2

您应该创建一个 IntentService。向服务发送意图以启动它。使用 LocalBroadcastManager(来自支持库)发回带有结果的意图。IntentService 在完成时会自行停止,这与常规服务不同。

如果用户在 AsyncTask 执行时旋转设备,则结果将丢失,因为 AsyncTask 线程与被旋转破坏的活动相关联。您可以在 StackOverflow上找到一个如何规避此问题的示例,但它比编写 IntentService 更多代码和更复杂。由于 IntentService 在自己的线程上,因此在销毁活动时它不会丢失。

public class MyIntentService extends IntentService {

    public static final String SERVICE_NAME ="whatever";

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        //Get input from the intent, do your http stuff here, 
        //  create a new intent to send back

        LocalBroadcastManager.getInstance(this).sendBroadcast(intentToSendBack);
    }
}

查看 IntentService 文档:Intent Service 大约在页面下方的 1/3

在您的活动中使用 LocalBroadcastManager 来监听返回的意图。您只需在 OnResume 事件处理程序中连接它并在 OnPause 处理程序中取消它。因此,在您的原始活动在轮换中被破坏后,新的活动将开始收听。LocalBroadcastManager 的魔力在第一个活动的销毁和第二个活动的创建之间的那一小段时间内将意图排队。

@Override
protected void onResume() {
    super.onResume();

    IntentFilter filter = new IntentFilter(MyIntentService.SERVICE_NAME);
    LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, filter);
}

@Override
protected void onPause() {
    super.onPause();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
}

private BroadcastReceiver onNotice = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
    //Do your UI stuff here....
    }
}

文档中有更多关于LocalBroadcastManager 的详细信息。LocalBroadcastManager 还有其他一些好的副作用。以这种方式发送的 Intent 不会离开应用程序范围,因此其他应用程序无法窥探您传递的数据,并且您的 Activity 会处理结果而不会被迫进入前台。

不要忘记在您的 AndroidManifest.xml 中注册该服务。

于 2013-06-13T19:58:45.773 回答
0

AsyncTask如果你在你的应用中做与网络相关的事情,无论你做什么,你都需要使用一个,因为你会得到一个NetowrkOnMainThreadException. 你不能在 UI 线程上做任何与网络相关的事情。由于服务在 UI 线程上运行,您仍然需要在服务中使用 AsyncTask。

因此,如果是我,如果您需要在完成后更新 UI,我不会担心该服务

于 2013-06-13T16:37:05.003 回答