【问题标题】:How to download multiple files concurrently using intentservice in Android?如何在Android中使用intentservice同时下载多个文件?
【发布时间】:2014-10-28 20:37:39
【问题描述】:

我想创建一个与此类似的服务(参考来自Here),以在Android 中异步下载多个文件。

public static class DownloadingService extends IntentService {
public static String PROGRESS_UPDATE_ACTION = DownloadingService.class
        .getName() + ".newDownloadTask";
private ExecutorService mExec;
private CompletionService<NoResultType> mEcs;
private LocalBroadcastManager mBroadcastManager;
private List<DownloadTask> mTasks;

public DownloadingService() {
    super("DownloadingService");
    mExec = Executors.newFixedThreadPool( 3 ); // The reason to use multiple thread is to download files asynchronously. 
    mEcs = new ExecutorCompletionService<NoResultType>(mExec);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return super.onStartCommand(intent, flags, startId);
}

@Override
protected void onHandleIntent(Intent intent) {

  while(true)
  {
    if( cursor <= totalDownloadQueue.size() -1) {   //totalDownloadQueue is a static ArrayList which contains numerous DownloadTask
        mEcs.submit(totalDownloadQueue.get(cursor)); 
        cursor++; // The variable cursor is also a static int variable. 
    }
  }// continuously observing the totalDownloadQueue. If any download item is added. Then the thread are dispatched to handle that.
    mExec.shutdown();
}

用户可以在不同片段的listview中选择下载项目。我的策略是,当用户选择项目并按下下载按钮时,这些项目将传递给负责下载文件的DownloadTask。然后将下载任务添加到totalDownloadQueue

这里有一些问题:

  1. 我知道intentservice 是由某些已定义的操作触发的。但是我想要创建一个后台服务来监视totalDownloadQueue,如果有任何新的downloadtask可用,那么就会调用一些线程来操作这些任务。

    如果我为这个定制的intentservice 这样做会有什么副作用?

    我应该使用什么替代类?请提供sample code及解释,谢谢。

  2. 据我所知,线程的初始化只被调用一次。如果我在应用程序开始时启动服务并且线程应该在用户终止应用程序时被杀死。(我的意思是当他swipe out窗口时。)用户退出应用程序后线程是否存在?

  3. 如果这种方法仍然不能解决异步下载文件的问题?我应该采取什么其他策略? 请提供一些示例代码或参考,以便我对其进行修改。

我花了 7 天时间处理复杂的需求,请大家帮忙!

【问题讨论】:

    标签: java android multithreading android-download-manager android-intentservice


    【解决方案1】:

    在 Android 中异步下载多个文件。

    我想你也想同时下载。

    我认为你误用了intentserviceintentservice 有一个 looper 和一个 handler 并且每次调用 start 都会为处理程序创建一条消息。所有消息都在looper queue 中排队,并且一次只提供一条。

    你应该使用正常的服务,不要使用intentservice,因为你想同时下载而不是一次。扩展服务类并在onCreate 方法中创建多个线程,每个线程可以从onStartCommand 获取消息。我不想复制和粘贴文档示例,因为我认为最好再次阅读所有文档。如果您阅读它,您将完全理解如何创建同时处理多个任务的服务,尽管它在示例中只创建了一个线程。

    http://developer.android.com/guide/components/services.html

    我想要的是创建一个后台服务来监视 总下载队列

    我认为你不需要那个。就在您创建downloadtask 呼叫服务时,您的message 被传递到服务类,在该类中您可以创建blockingqueue 以通过threads 处理您的消息。

    用户退出应用后线程是否存在?

    是的,也许不是。这取决于进程,如果进程存在是,但如果进程已被破坏,否。再次阅读进程的lifecycle 以了解哪个进程被android杀死或保留。

    http://developer.android.com/guide/components/processes-and-threads.html

    如果这种方法仍然不能解决下载文件的问题 异步?我应该采取什么其他策略?请提供 一些示例代码或参考,以便我可以对其进行修改。

    您可以使用downloadmanager,但它会按顺序下载。

    http://developer.android.com/reference/android/app/DownloadManager.html

    http://blog.vogella.com/2011/06/14/android-downloadmanager-example/

    【讨论】:

    • 好吧,我在构造函数中有新的多个线程,使用ExecutorService。而且这里的文档也支持这种设计。 https://developer.android.com/training/multiple-threads/create-threadpool.html
    • 是的,文档支持,但创建意图服务是为了一次使用一项工作,服务文档是这么说的。它说使用多线程使用startservice而不是intentservice。顺便说一句,您的应用可以随心所欲。
    • 那我具体看看service结合ExcutorService如何实现文件同时下载。如果您有这样的代码供我参考,我将不胜感激。
    • 一个service是一个后台线程,如果用户选择了更多的文件下载,如何让服务做下载任务?我是否应该创建一个队列来缓存下载任务并且它也是服务的observed?谢谢!!!
    • 但是你不能用 volley 下载大文件所以它不是下载管理器它是用于小文件的
    【解决方案2】:

    IntenServiceAsyncTask 提供单个工作线程,因此无法同时下载多个图像。但是,我强烈建议ThreadPoolExecutor 满足您的要求。它基本上创建了一个线程池,这些线程池根据您应用的任务数量或要下载的文件数量来扩展/收缩。 THreadPoolExecutor 几乎可以处理线程管理的各个方面,并且非常高效。您使用此代码示例中的 as 创建单个执行程序:

    ExecutorService tpExecutor=
            new ThreadPoolExecutor(
                    coreSize,      // the basic number of threads, when a task is added to the queue
                                   // a new thread is created if nrOfThreads < coreSize  
                    maxPoolSize,   // maximum number of threads created
                    keepAliveTime,
                    TimeUnit.MILLISECONDS,
                    new LinkedBlockingQueue<Runnable>()
                    ); 
    

    您可以通过执行runnables提交多个下载任务:

    tpExecutor.execute(new Runnable());
    

    【讨论】:

    • 我使用Executors.newFixedThreadPool( 3 ); 运行多个任务。但我不知道使用IntentService 是否正确,我需要更具体的代码。谢谢。
    • 你的意思是我可以将下载路径URL和相关参数传递给新的Runnable()实例对象,它就开始下载了吗?顺便说一句:我发现当我多次调用startService() 时,它失败了。但是用户不能一开始就决定要下载什么,他可能想在第一次决定后下载更多的文件。这会导致service 类出错。
    • 如果 Runnable 任务的数量大于 LinkedBlockingQueue 大小会发生什么?据我所知,execute 就像在池中注册一个事件。如果没有空闲线程并且没有超过队列大小的限制,就会入队。
    • 如果当前大小没有达到maxSizeThreadPoolExecutor会创建一个新线程,否则任务会被排队。
    【解决方案3】:

    从听起来你可能会受益于使用来自ASyncTaskonProgressUpdate 方法,它可以让你随时了解进度。也许通读类描述——这听起来正是你所需要的。它还附带大量示例代码!

    希望我能有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-16
      • 2018-09-26
      • 2023-03-22
      • 1970-01-01
      • 2013-02-07
      • 1970-01-01
      相关资源
      最近更新 更多