运行Android中的多个并行下载 [英] Running multiple parallel downloads in Android

查看:179
本文介绍了运行Android中的多个并行下载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我延长 IntentService 来建立我的 DonwloadService 类。这是确定的,但一个下载队列已经建立和2下载不得不等待1到成品等。

First, I extended IntentService to build my DonwloadService class. It was OK, but a download queue had been created and 2nd download had to wait for the 1st to finished etc.

所以我决定延长服务类(遵循的文档)。我刚刚添加下载功能和功能发布的结果(在活动接收器收听):

So I decided to extend Service class (following the docs). I've just added download function and function for publishing results (listened by receiver in activity):

    public class DownloadService extends Service
{
    private static final String TAG = DownloadService.class.getSimpleName();

    public static final String EXTRA_DOWNLOAD = "EXTRA_DOWNLOAD";
    public static final String EXTRA_POSITION = "EXTRA_POSITION";
    public static final String INTENT_NOTIFICATION = "INTENT_NOTIFICATION";
    public static final String EXTRA_RESULT = "EXTRA_RESULT";
    public static final String EXTRA_PROGRESS = "EXTRA_PROGRESS";
    public static final String EXTRA_PATH = "EXTRA_PATH";
    public static final String EXTRA_INDETERMINABLE = "EXTRA_INDETERMINABLE";
    public static final int RESULT_PROGRESS = 123;

    private int mResult = Activity.RESULT_CANCELED;

    private Looper mServiceLooper;
    private ServiceHandler mServiceHandler;

    private final class ServiceHandler extends Handler
    {
        public ServiceHandler(Looper looper)
        {
            super(looper);
        }

        @Override
        public void handleMessage(Message message)
        {
            // Download file
            download(message.getData());

            // Stop the service using the startId, so that we don't stop
            // the service in the middle of handling another job
            stopSelf(message.arg1);
        }
    }

    @Override
    public void onCreate()
    {
        // Start up the thread running the service.  Note that we create a
        // separate thread because the service normally runs in the process's
        // main thread, which we don't want to block.  We also make it
        // background priority so CPU-intensive work will not disrupt our UI.
        HandlerThread handlerThread = new HandlerThread("DownloadServiceStartArguments",
                Process.THREAD_PRIORITY_BACKGROUND);
        handlerThread.start();

        // Get the HandlerThread's Looper and use it for our Handler
        mServiceLooper = handlerThread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        // For each start request, send a message to start a job and deliver the
        // start ID so we know which request we're stopping when we finish the job
        Message message = mServiceHandler.obtainMessage();
        message.setData(intent.getExtras());
        message.arg1 = startId;
        mServiceHandler.sendMessage(message);

        return START_REDELIVER_INTENT;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent)
    {
        // No binding provided
        return null;
    }

    @Override
    public void onDestroy()
    {
        Log.d(TAG, "Service done");
    }

    /**
     * Handles file download
     *
     * @param bundle
     */
    private void download(Bundle bundle)
    {
        if (bundle != null) {
            return;
        }

        Download download = bundle.getParcelable(EXTRA_DOWNLOAD);
        int position = bundle.getInt(EXTRA_POSITION, -1);

        File downloadedFile = new File(Environment.getExternalStorageDirectory(), position + ".jpg");
        if (downloadedFile.exists()) {
            downloadedFile.delete();
        }

        FileOutputStream fileOutputStream = null;

        int filesize = -1;

        try {

            fileOutputStream = new FileOutputStream(downloadedFile.getPath());

            URL url = new URL(download.getUrl());
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.connect();

            filesize = connection.getContentLength();

            InputStream reader = new BufferedInputStream(connection.getInputStream());

            byte data[] = new byte[1024];

            int next = -1;
            int total = 0;
            while ((next = reader.read(data)) != -1) {
                mResult = RESULT_PROGRESS;
                total += next;
                publishResult(downloadedFile.getAbsolutePath(),
                        (filesize > 0) ? Math.round(total * 100 / filesize) : Math.round(total / 1024),
                        position, filesize <= 0);

                fileOutputStream.write(data, 0, next);
            }

            mResult = Activity.RESULT_OK;

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        publishResult(downloadedFile.getAbsolutePath(), 100, position, filesize <= 0);

    }

    private void publishResult(String downloadPath, int progress, int positionInList,
                               boolean indeterminable)
    {
        Intent intent = new Intent(INTENT_NOTIFICATION);
        intent.putExtra(EXTRA_PATH, downloadPath);
        intent.putExtra(EXTRA_PROGRESS, progress);
        intent.putExtra(EXTRA_POSITION, positionInList);
        intent.putExtra(EXTRA_INDETERMINABLE, indeterminable);
        intent.putExtra(EXTRA_RESULT, mResult);
        sendBroadcast(intent);
    }
}

但仍然有一个下载队列,没有并行下载。

But still there is a download queue, no parallel downloads.

推荐答案

如果你想在不同的数据集多次运行任务,但你只需要一个执行同时运行,一​​个 IntentService 适合您的需要。要自动运行的任务,只要有资源,或允许多个任务在同一时间(或两者)上运行,你需要提供的线程管理的集合。要做到这一点,使用的ThreadPoolExecutor 的一个实例,当其在池中的线​​程空闲运行从队列的任务​​。要运行一个任务,你所要做的就是把它添加到队列中。

If you want to run a task repeatedly on different sets of data, but you only need one execution running at a time, an IntentService suits your needs. To automatically run tasks as resources become available, or to allow multiple tasks to run at the same time (or both), you need to provide a managed collection of threads. To do this, use an instance of ThreadPoolExecutor, which runs a task from a queue when a thread in its pool becomes free. To run a task, all you have to do is add it to the queue.

参考:
用于创建多个线程管理器

这篇关于运行Android中的多个并行下载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆