84669 personnes étudient
152542 personnes étudient
20005 personnes étudient
5487 personnes étudient
7821 personnes étudient
359900 personnes étudient
3350 personnes étudient
180660 personnes étudient
48569 personnes étudient
18603 personnes étudient
40936 personnes étudient
1549 personnes étudient
1183 personnes étudient
32909 personnes étudient
想实现一个后台下载的功能,类似百度地图离线包下载,当下载任务在进行时可以返回其他界面进行其他的操作,下载列表所在的界面为activity1,其他界面为activity2,当在activity1中点击几个任务进行下载时,返回了activity2进行其他操作,过一段时间后再进入activity1怎么显示当前的下载进度?
ringa_lee
下载任务显然需要在主线程之外处理。而从当前执行下载任务的activity按了返回键,然后再次进入后,该activity已经被销毁并且重建了,并且一般情况下,在activity被销毁后,我们应该清理新建的线程,以避免无法预料的后果。所以activity重建后显示当前下载信息的各种UI组件也就无法显示正确的状态了。而Service与UI无关,可以在后台长时间运行;Bound service 更是允许 app 组件和 service 沟通:发送请求(比如下载请求)、获取状态(比如下载进度)。
所以,一种可行的解决办法是:
AsyncTask 负责另起一个线程下载,并且定义一个接口,实现该接口就可以获得下载进度及其它下载信息。
Bound Service 负责在后台启动 AsyncTask,并且管理该下载任务;实现 AsyncTask 定义的接口,把获取的下载信息以广播的形式发送出去;
Activity 在绑定到 service 后,就可以通过 service 启动一个下载任务;然后实现一个 broadcast receiver,接收下载信息并更新UI.
如果对service不了解,可以点这里链接1;对绑定也不了解,可以点这里链接2。
public class DownloadTask extends AsyncTask<Void, Integer, Long> { // 维护下载大小、下载进度、下载速率等信息。 private long downloadPercent; // 构造器,指定下载的url和存储路径。 public DownloadTask(Context context, String url, String path); @Override protected Long doInBackground(Void... params) { // 根据获取的url,执行下载任务。 } @Override protected void onProgressUpdate(Integer... progress) { // 定义一个callback,实现该callback的即可获得进度的更新。 if (listener != null) listener.updateProcess(this); }
public class DownloadService extends Service { // Activity绑定该service后,就可以调用这个方法启动一个下载任务。 public void startDownloadTask(String url) { DownloadTask task = newDownloadTask(url); task.execute(); } private DownloadTask newDownloadTask(String url) throws MalformedURLException { // 实现该接口就可以获得下载进度及其它下载信息,然后以广播的形式把获取的信息发送出去。 DownloadTaskListener taskListener = new DownloadTaskListener() { @Override public void updateProcess(DownloadTask task) { Intent updateIntent = new Intent(ACTION_DOWNLOADING_STATUS); updateIntent.putExtra(MyIntents.PROCESS_PROGRESS, task.getDownloadPercent()); sendBroadcast(updateIntent); } }; return new DownloadTask(this, url, /path/to/store/, taskListener); } }
public class DownloadActivity extends FragmentActivity { // 在onStart中绑定service,注册receiver protected void onStart(); // 在onStop中取消绑定,取消注册receiver protected void onStop(); // 实现一个ServiceConnection,在onServiceConnected()回调方法中获取service private ServiceConnection mConnection = new ServiceConnection() {} // 实现一个BroadcastReceiver,在onReceive()回调方法中获取intent,从中解析下载信息然后更新UI. private BroadcastReceiver mDownloadingStatusReceiver = new BroadcastReceiver() {} // 获取service后,就可以启动一个下载任务了。 mService.startDownloadTask(URL); }
完整的代码可以从这里获取 https://github.com/li2/DownloadDemo这仅仅是一个demo,用于演示bound service和async task是如何实现后台下载任务的。该Demo从这个项目里yingyixu/android-download-manager (1) 借用了核心代码;(2) 使用 Binder class实现service,代替原工程中使用的AIDL方式(因为该方式实现复杂,而Binder已经可以满足你的需求,而且容易理解);(3) 删除了管理多个下载任务的代码。
建议了解实现方法后,直接使用第三方框架。
据我所知下载进度断点续传什么的是要存在数据库里的,所以把下载进度存在数据库里,下次进入的时候显示这个下载进度,就好了
既然是后台下载,当这个界面再次显示的时候,获取正在后台下载的任务,显示到当前界面不就行了吗
可以写一个Service进行后台下载工作,Activity1和该Service绑定,通过Intent及Binder来实现Service和Activity1进行数据交换(即你说的从Activity2回到Activity1时下载进度变化处理),具体实现你需要对Service,Service跟Activity交互有更深的理解了,可以照这个思路去找资料学习和实现,祝你成功。
在service中进行下载,Activity1使用bindservice()方法与service绑定,并在service中设置一个回调方法。下载的时候调用这个回调方法把进度传递给Activity1
下载任务显然需要在主线程之外处理。
而从当前执行下载任务的activity按了返回键,然后再次进入后,该activity已经被销毁并且重建了,并且一般情况下,在activity被销毁后,我们应该清理新建的线程,以避免无法预料的后果。所以activity重建后显示当前下载信息的各种UI组件也就无法显示正确的状态了。
而Service与UI无关,可以在后台长时间运行;Bound service 更是允许 app 组件和 service 沟通:发送请求(比如下载请求)、获取状态(比如下载进度)。
所以,一种可行的解决办法是:
AsyncTask 负责另起一个线程下载,并且定义一个接口,实现该接口就可以获得下载进度及其它下载信息。
Bound Service 负责在后台启动 AsyncTask,并且管理该下载任务;实现 AsyncTask 定义的接口,把获取的下载信息以广播的形式发送出去;
Activity 在绑定到 service 后,就可以通过 service 启动一个下载任务;然后实现一个 broadcast receiver,接收下载信息并更新UI.
如果对service不了解,可以点这里链接1;对绑定也不了解,可以点这里链接2。
AsyncTask负责另起一个线程下载
Bound Service负责在后台启动AsyncTask,并管理下载任务
Activity负责绑定service,实现一个 broadcast receiver,接收下载信息并更新UI
完整的代码可以从这里获取 https://github.com/li2/DownloadDemo
这仅仅是一个demo,用于演示bound service和async task是如何实现后台下载任务的。
该Demo从这个项目里yingyixu/android-download-manager (1) 借用了核心代码;(2) 使用 Binder class实现service,代替原工程中使用的AIDL方式(因为该方式实现复杂,而Binder已经可以满足你的需求,而且容易理解);(3) 删除了管理多个下载任务的代码。
建议了解实现方法后,直接使用第三方框架。
据我所知下载进度断点续传什么的是要存在数据库里的,所以把下载进度存在数据库里,下次进入的时候显示这个下载进度,就好了
既然是后台下载,当这个界面再次显示的时候,获取正在后台下载的任务,显示到当前界面不就行了吗
可以写一个Service进行后台下载工作,Activity1和该Service绑定,通过Intent及Binder来实现Service和Activity1进行数据交换(即你说的从Activity2回到Activity1时下载进度变化处理),具体实现你需要对Service,Service跟Activity交互有更深的理解了,可以照这个思路去找资料学习和实现,祝你成功。
在service中进行下载,Activity1使用bindservice()方法与service绑定,并在service中设置一个回调方法。下载的时候调用这个回调方法把进度传递给Activity1