草庐IT

Android 多个下载暂停在 ListView 中恢复并更新进度

coder 2023-12-03 原文

我正在尝试使用进度条在 ListView 中下载多个文件。我实现的是,我可以开始特定的下载,使用 AsyncTask 暂停/恢复它并更新进度条(对于单个文件),这部分效果很好

我的问题是我无法同时下载多个文件,当我离开 ListView 到另一个屏幕时,虽然我的下载在后台进行,但进度没有更新,进度条显示 0 进度,好像它没有下载但它一直在后台下载。

最佳答案

终于找到了答案,比我想象的简单多了,如下

  1. 创建一个服务,具有用于下载的Asynctask和值的哈希表(url, Asynctask)
  2. 在单击列表项时传递值(url,Asynctask),并检查该哈希表是否已经包含该值,如果是,则取消该 Asynctask 任务,如果不将其添加到哈希表并启动 Asynctask
  3. 现在为了更新我的适配器中的进度,我运行了一个线程,该线程遍历hashtable 并使用BroadcastListener 传递值。
  4. 并在 Activity 中拦截广播并根据可见的ListItem更新进度

PS:如果有人需要一些代码,我可以提供上面解释的基本代码

public class DownloadingService extends Service {
public static String PROGRESS_UPDATE_ACTION = DownloadingService.class.getName() + ".progress";

private static final long INTERVAL_BROADCAST = 800;
private long mLastUpdate = 0;
private Hashtable<String, DownloadFile> downloadTable;

private LocalBroadcastManager broadcastManager;

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    MessageEntity entityRecieved = (MessageEntity) intent.getSerializableExtra("ENTITY");
    queueDownload(entityRecieved);
    return super.onStartCommand(intent, flags, startId);
}

private void queueDownload(MessageEntity entityRecieved){
    if (downloadTable.containsKey(entityRecieved.getPacketID())) {
        DownloadFile downloadFile = downloadTable.get(entityRecieved.getPacketID());
        if (downloadFile.isCancelled()) {
            downloadFile = new DownloadFile(entityRecieved);
            downloadTable.put(entityRecieved.getPacketID(), downloadFile);
            startDownloadFileTask(downloadFile);
        } else {
            downloadFile.cancel(true);
            downloadTable.remove(entityRecieved.getPacketID());
        }

    } else {
        DownloadFile downloadFile = new DownloadFile(entityRecieved);
        downloadTable.put(entityRecieved.getPacketID(), downloadFile);
        startDownloadFileTask(downloadFile);
    }
}

@Override
public void onCreate() {
    super.onCreate();
    downloadTable = new Hashtable<String, DownloadFile>();
    broadcastManager = LocalBroadcastManager.getInstance(this);
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
void startDownloadFileTask(DownloadFile asyncTask) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    else
        asyncTask.execute();
}

private void publishCurrentProgressOneShot(boolean forced) {
    if (forced || System.currentTimeMillis() - mLastUpdate > INTERVAL_BROADCAST) {
        mLastUpdate = System.currentTimeMillis();
        int[] progresses = new int[downloadTable.size()];
        String[] packetIds = new String[downloadTable.size()];
        int index = 0;
        Enumeration<String> enumKey = downloadTable.keys();
        while (enumKey.hasMoreElements()) {
            String key = enumKey.nextElement();
            int val = downloadTable.get(key).progress;
            progresses[index] = val;
            packetIds[index++] = key;
        }
    Intent i = new Intent();
    i.setAction(PROGRESS_UPDATE_ACTION);
    i.putExtra("packetIds", packetIds);
    i.putExtra("progress", progresses);
    mBroadcastManager.sendBroadcast(i);
}

class DownloadFile extends AsyncTask<Void, Integer, Void> {
    private MessageEntity entity;
    private File file;
    private int progress;

    public DownloadFile(MessageEntity entity) {
        this.entity = entity;
    }

    @Override
    protected Void doInBackground(Void... arg0) {
        String filename = entity.getMediaURL().substring(entity.getMediaURL().lastIndexOf('/') + 1);
        file = new File(FileUtil.getAppStorageDir().getPath(), filename);
        downloadFile(entity.getMediaURL(), file); 
        return null;
    }

    public String downloadFile(String download_file_path, File file) {
        int downloadedSize = 0;
        int totalSize = 0;
        try {
            // download the file here
            while ((bufferLength = inputStream.read(buffer)) > 0 && !isCancelled()) {

                progress = percentage;
                publishCurrentProgressOneShot(true);
            }


        } catch (final Exception e) {
            return null;
        }

        return file.getPath();
    }

}

关于Android 多个下载暂停在 ListView 中恢复并更新进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26944977/

有关Android 多个下载暂停在 ListView 中恢复并更新进度的更多相关文章

  1. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  4. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  5. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  6. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  7. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  8. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

  9. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  10. ruby - 使用多个数组创建计数 - 2

    我正在尝试按0-9和a-z的顺序创建数字和字母列表。我有一组值value_array=['0','1','2','3','4','5','6','7','8','9','a','b','光盘','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','','u','v','w','x','y','z']和一个组合列表的数组,按顺序,这些数字可以产生x个字符,比方说三个list_array=[]和一个当前字母和数字组合的数组(在将它插入列表数组之前我会把它变成一个字符串,]current_combo['0','0','0']

随机推荐