Android后台下载问题
ringa_lee
ringa_lee 2017-04-17 14:49:17
0
5
417

想实现一个后台下载的功能,类似百度地图离线包下载,当下载任务在进行时可以返回其他界面进行其他的操作,下载列表所在的界面为activity1,其他界面为activity2,当在activity1中点击几个任务进行下载时,返回了activity2进行其他操作,过一段时间后再进入activity1怎么显示当前的下载进度?

ringa_lee
ringa_lee

ringa_lee

全部回覆(5)
刘奇

下載任務顯然需要在主執行緒之外處理。
而從目前執行下載任務的activity按了返回鍵,然後再次進入後,該activity已經被銷毀並且重建了,並且一般情況下,在activity被銷毀後,我們應該清理新建的線程,以避免無法預料的後果。所以activity重建後顯示目前下載資訊的各種UI元件也就無法顯示正確的狀態了。
而Service與UI無關,可以在後台長時間運作;Bound service 更是允許 app 元件和 service 溝通:發送要求(例如下載要求)、取得狀態(例如下載進度)。

所以,一個可行的解決方法是:

  1. AsyncTask 負責另起一個線程下載,並且定義一個接口,實現該接口就可以獲得下載進度及其它下載信息。

  2. Bound Service 負責在後台啟動 AsyncTask,並且管理該下載任務;實現 AsyncTask 定義的接口,把獲取的下載信息以廣播的形式發送出去;

  3. Activity 在綁定到 service 後,就可以透過 service 啟動一個下載任務;然後實作一個 broadcast receiver,接收下載資訊並更新UI.

如果對service不了解,可以點這裡連結1;對綁定也不了解,可以點這裡連結2。

AsyncTask負責另一個執行緒下載

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);
    }

Bound Service負責在背景啟動AsyncTask,並管理下載任務

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);
    }
}

Activity負責綁定service,實作一個 broadcast receiver,接收下載資訊並更新UI

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互動有更深的理解了,可以照這個思路去找資料學習和實現,祝你成功。

Peter_Zhu

在service中進行下載,Activity1使用bindservice()方法與service綁定,並在service中設定回調方法。下載的時候呼叫這個回呼方法把進度傳給Activity1

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!