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