84669 人学习
152542 人学习
20005 人学习
5487 人学习
7821 人学习
359900 人学习
3350 人学习
180660 人学习
48569 人学习
18603 人学习
40936 人学习
1549 人学习
1183 人学习
32909 人学习
想实现一个后台下载的功能,类似百度地图离线包下载,当下载任务在进行时可以返回其他界面进行其他的操作,下载列表所在的界面为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