我有几个URL
我需要从中获取数据,这应该按顺序进行,一个接一个。请求这些URL
s返回的数据量比较大。我需要能够重新安排失败的特定下载。
最好的方法是什么?我应该使用IntentService
,Loaders
还是别的什么?
附加说明:我不仅需要下载,还需要后处理数据(在数据库中创建表,用数据填充等)。所以DownloadManger
在这里帮不上忙。
我有几个URL
我需要从中获取数据,这应该按顺序进行,一个接一个。请求这些URL
s返回的数据量比较大。我需要能够重新安排失败的特定下载。
最好的方法是什么?我应该使用IntentService
,Loaders
还是别的什么?
附加说明:我不仅需要下载,还需要后处理数据(在数据库中创建表,用数据填充等)。所以DownloadManger
在这里帮不上忙。
我会使用一个IntentService
.
它具有许多适合您需求的优点,包括无需运行应用程序即可下载数据以及支持使用setIntentRedelivery()
.
您可以为特定作业设置多个标识符,您需要使用Intent
附加功能执行,并且您可以使用跟踪进度SharedPreferences
- 这样您也可以在之前取消工作时恢复工作。
我会为此建议一项服务。有服务可以解决很多问题
它将允许向应用程序异步报告进度,因此您可以根据数据的下载状态启用或禁用应用程序中的特定 gui
即使用户切换到其他应用程序或关闭应用程序,它也允许您继续下载。
将允许您与服务器建立独立的通信以优先下载而无需用户交互。
最简单的方法大概是使用系统DownloadManager http://developer.android.com/reference/android/app/DownloadManager.html
(用我的电话接听,所以请原谅缺乏格式)
尝试WakefulIntentService
创建一个长期运行的作业,该作业使用唤醒锁来保持您的任务处于活动状态并运行https://github.com/commonsguy/cwac-wakeful。
此外,如果您的整个应用程序进程被终止,您可能需要考虑使用来自 Square 的 Tape之类的东西将任务队列持久化到磁盘
我认为要走的路是在数组中加载 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));
}
}
希望这有帮助
我刚刚完成了一个开源库,可以完全满足您的需求。使用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);
}
}));
您可以指定其他数据类型,这些数据类型将返回不同的对象类型,例如JSONObject
、String
、Document
等。
类似于@Murtuza Kabul,我会说使用服务,但它比这有点复杂。我们有类似的情况与不断的互联网访问和更新有关,尽管我们更加关注保持服务运行。我将尝试突出主要功能,而不会让您淹没在太多细节中(并且代码归公司所有;))
android.permission.RECEIVE_BOOT_COMPLETED
许可和BroadcastReceiver
监听android.intent.action.BOOT_COMPLETED
以唤醒服务。
不要将服务链接到 Activity,您希望它一直运行。例如,我们称context.startService(new Intent(context.getApplicationContext(), OurService.class))
服务类只是一个简单的类,它注册并调用一个OurServiceHandler
(在我们的例子中,我们触发重复检查并Handler
管理“滴答声”)
我们有一个OurServiceRunnable
which 是一个单例,Handler
每个测试都会对其进行检查和调用。它可以防止重叠更新。它委托给一个OurServiceWorker
做实际的提升。
听起来很沉重,但您要确保服务始终运行,始终滴答作响(通过Handler
),但一次只运行一次检查。如果您使用标准的 SqlLite DbHelper 范例,您也会遇到数据库问题,因为您无法在多个线程上打开数据库,并且您肯定希望通过主线程访问 Internet。我们的 hack 是java.util.concurrent.locks.ReentrantLock
对 DB 的保护访问,但您可能会在 UI 线程上保留 DB 访问权限并通过Handler
.
除此之外,只需在“获取任务、下载任务、完成任务”方面保持下载的原子性,或者使其能够从失败状态中恢复,例如下载成功,尝试完成。
你应该看看 volley 库:
http://www.javacodegeeks.com/2013/06/android-volley-library-example.html
在 google io 2013 上还有一段作者的有趣视频:
http://www.youtube.com/watch?v=yhv8l9F44qo
主要是因为它简化了管理连接检查、连接中断、队列管理、重试、恢复等许多繁琐任务的过程。
引用 javacodegeeks “使用 Volley 的优势:
来自 dennisdrew 的更新:对于大文件,最好使用 volley 的变体,它授权使用另一个 http 客户端实现。此链接提供了更多详细信息:
关于此修改的凌空文章:
http://ogrelab.ikratko.com/android-volley-examples-samples-and-demos/
github文件详细信息:
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();
}
}