22

我有几个URL我需要从中获取数据,这应该按顺序进行,一个接一个。请求这些URLs返回的数据量比较大。我需要能够重新安排失败的特定下载。

最好的方法是什么?我应该使用IntentServiceLoaders还是别的什么?

附加说明:我不仅需要下载,还需要后处理数据(在数据库中创建表,用数据填充等)。所以DownloadManger在这里帮不上忙。

4

9 回答 9

12

我会使用一个IntentService.

它具有许多适合您需求的优点,包括无需运行应用程序即可下载数据以及支持使用setIntentRedelivery().

您可以为特定作业设置多个标识符,您需要使用Intent附加功能执行,并且您可以使用跟踪进度SharedPreferences- 这样您也可以在之前取消工作时恢复工作。

于 2013-07-11T13:58:24.757 回答
5

我会为此建议一项服务。有服务可以解决很多问题

  • 它将允许向应用程序异步报告进度,因此您可以根据数据的下载状态启用或禁用应用程序中的特定 gui

  • 即使用户切换到其他应用程序或关闭应用程序,它也允许您继续下载。

  • 将允许您与服务器建立独立的通信以优先下载而无需用户交互。

于 2013-07-11T13:48:54.360 回答
5

最简单的方法大概是使用系统DownloadManager http://developer.android.com/reference/android/app/DownloadManager.html

(用我的电话接听,所以请原谅缺乏格式)

于 2013-07-11T13:34:57.187 回答
3

尝试WakefulIntentService创建一个长期运行的作业,该作业使用唤醒锁来保持您的任务处于活动状态并运行https://github.com/commonsguy/cwac-wakeful

此外,如果您的整个应用程序进程被终止,您可能需要考虑使用来自 Square 的 Tape之类的东西将任务队列持久化到磁盘

于 2013-07-15T04:42:50.923 回答
2

我认为要走的路是在数组中加载 url,然后启动 AsyncTask,向 onPostExecute 返回一个布尔值,指示操作是否成功。然后,保持全局 int 索引,如果成功,您可以使用下一个索引运行 AsyncTask,否则使用相同的索引。这是一个伪代码

private int index=0;
//this array must be loaded with urls
private ArrayList<String> urlsArray;

new MyDownloaderAsyncTask().execute(urlsArray.get(index));


class MyDownloaderAsyncTask extends AsyncTask<String,String,Boolean>{

@Override
doInBackground(String... input){

//downlaod my data is the function which download data and return a boolean
return downloadMyData();

}

@Override
onPostExecute(Boolean result){

if(result)
    new MyDownloaderAsyncTask().execute(urlsArray.get(++index));
else
    new MyDownloaderAsyncTask().execute(urlsArray.get(index));
}


}

希望这有帮助

于 2013-07-08T16:41:02.277 回答
1

我刚刚完成了一个开源库,可以完全满足您的需求。使用droidQuery,您可以执行以下操作:

$.ajax(new AjaxOptions().url("http://www.example.com")
                        .type("GET")
                        .dataType("JSON")
                        .context(this)
                        .success(new Function() {
                            @Override
                            public void invoke($ droidQuery, Object... params) {
                                //since dataType is JSON, params[0] is a JSONObject
                                JSONObject obj = (JSONObject) params[0];
                                //TODO handle data
                                //TODO start the next ajax task
                            }
                        })
                        .error(new Function() {
                            @Override
                            public void invoke($ droidQuery, Object... params) {
                                AjaxError error = params[0];
                                //TODO adjust error.options before retry:
                                $.ajax(error.request, error.options);
                            }
                        }));

您可以指定其他数据类型,这些数据类型将返回不同的对象类型,例如JSONObjectStringDocument等。

于 2013-07-14T18:46:07.600 回答
1

类似于@Murtuza Kabul,我会说使用服务,但它比这有点复杂。我们有类似的情况与不断的互联网访问和更新有关,尽管我们更加关注保持服务运行。我将尝试突出主要功能,而不会让您淹没在太多细节中(并且代码归公司所有;))

  1. android.permission.RECEIVE_BOOT_COMPLETED许可和BroadcastReceiver监听android.intent.action.BOOT_COMPLETED以唤醒服务。

  2. 不要将服务链接到 Activity,您希望它一直运行。例如,我们称context.startService(new Intent(context.getApplicationContext(), OurService.class))

  3. 服务类只是一个简单的类,它注册并调用一个OurServiceHandler(在我们的例子中,我们触发重复检查并Handler管理“滴答声”)

  4. 我们有一个OurServiceRunnablewhich 是一个单例,Handler每个测试都会对其进行检查和调用。它可以防止重叠更新。它委托给一个OurServiceWorker做实际的提升。

听起来很沉重,但您要确保服务始终运行,始终滴答作响(通过Handler),但一次只运行一次检查。如果您使用标准的 SqlLite DbHelper 范例,您也会遇到数据库问题,因为您无法在多个线程上打开数据库,并且您肯定希望通过主线程访问 Internet。我们的 hack 是java.util.concurrent.locks.ReentrantLock对 DB 的保护访问,但您可能会在 UI 线程上保留 DB 访问权限并通过Handler.

除此之外,只需在“获取任务、下载任务、完成任务”方面保持下载的原子性,或者使其能够从失败状态中恢复,例如下载成功,尝试完成。

于 2013-07-15T04:46:02.840 回答
0

你应该看看 volley 库:

http://www.javacodegeeks.com/2013/06/android-volley-library-example.html

在 google io 2013 上还有一段作者的有趣视频:

http://www.youtube.com/watch?v=yhv8l9F44qo

主要是因为它简化了管理连接检查、连接中断、队列管理、重试、恢复等许多繁琐任务的过程。

引用 javacodegeeks “使用 Volley 的优势:

  1. Volley 自动调度所有网络请求。这意味着 Volley 将处理您的应用程序执行的所有网络请求,以从 Web 获取响应或图像。
  2. Volley 提供透明的磁盘和内存缓存。
  3. Volley 提供了强大的取消请求 API。这意味着您可以取消单个请求,也可以设置要取消的请求块或范围。
  4. Volley 提供了强大的定制能力。
  5. Volley 提供调试和跟踪工具”

来自 dennisdrew 的更新:对于大文件,最好使用 volley 的变体,它授权使用另一个 http 客户端实现。此链接提供了更多详细信息:

关于此修改的凌空文章:

http://ogrelab.ikratko.com/android-volley-examples-samples-and-demos/

github文件详细信息:

https://github.com/ogrebgr/android_volley_examples/blob/master/src/com/github/volley_examples/toolbox/ExtHttpClientStack.java

于 2013-07-15T10:42:18.840 回答
0
public class FetchDataFromDBThread implements Runnable {

    /*
     * Defines the code to run for this task.
     */
    @Override
    public void run() {
        // Moves the current Thread into the background
        android.os.Process
                .setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);

        FetchDataFromDB();
    }

}
于 2013-07-17T11:40:44.920 回答