使用 DownloadManager 时 ListView 中的 Android ProgressBar

2023-11-21

我有一个 ListView,其中每个项目代表一个 PDF 文件。当用户单击某个项目时,应用程序必须将文件下载到外部存储上。 现在下载无法正常运行,但这不是问题所在。我想要一个进度条(旋转轮样式)在下载文件时出现在列表的每个项目旁边。

我的问题是:我找不到如何让旋转轮出现。在使用下载管理器之前,我尝试使用 AsyncTask 并且旋转轮可以工作。

这是我的代码:

CategoryActivity.java(ListView的活动)

@Override
public void onItemClick(AdapterView<?> parent, View view,
    int position, long id) {
    // Récupère les valeurs depuis ListItem
    udl = ((TextView) view.findViewById(R.id.udl)).getText().toString();
    // This is the spinning wheel
    loader = ((ProgressBar) view.findViewById(R.id.spinWheel2));

    filepath = dirpath + udl + ".pdf";
    File file = new File(filepath);
    if (file.exists()) {

        // If the file exists, I open it

    }else{ // Else I download it
        // Setting the spinning wheel to VISIBLE
        loader.setVisibility(View.VISIBLE);

        SharedPreferences codeSaveUrl = getSharedPreferences(PREFS_TEXT,Context.MODE_PRIVATE);
        url2 = codeSaveUrl.getString("defaut", ""); // Code Organisation
        // Constructing the uriString
        uri = url10 + url2 + "&file=" + udl ;

        Uri myuri = Uri.parse(uri);
        DownloadManager mgr=(DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE);
        mgr.enqueue(new DownloadManager.Request(myuri)
        .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI |DownloadManager.Request.NETWORK_MOBILE)
        .setAllowedOverRoaming(false)
        .setTitle(udl + ".pdf")
        .setDescription("Téléchargement en cours")
        .setDestinationInExternalPublicDir("/Protocols/", (udl+".pdf"))
        .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE));                    

        // Hiding the spinning wheel
        loader.setVisibility(View.GONE);

    }
}

请注意,如果我不让旋转轮消失,则单击该项目后它将始终可见。用线隐藏它,它甚至不会出现。


EDIT :
我添加了一个广播接收器。

将这两行放入 onCreate() 中:

final DownloadManager mgr=(DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE);
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

并添加了这个:

BroadcastReceiver onComplete = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            loader.setVisibility(View.GONE);
        }
    };

    @Override
    public void onDestroy(){
        super.onDestroy();
        unregisterReceiver(onComplete);
    }

EDIT 2 :好的,这是我所做的一些更改:

我将下载的 id 保存在变量中:

lastDownload = mgr.enqueue(new DownloadManager.Request(myuri)
                .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI |DownloadManager.Request.NETWORK_MOBILE)
                .setAllowedOverRoaming(false)
                .setTitle(udl + ".pdf")
                .setDescription("Téléchargement en cours")
                .setDestinationInExternalPublicDir("/Protocols/", (udl+".pdf"))
                .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED));

根据下载的状态,我想做不同的事情:

BroadcastReceiver onComplete = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            Cursor c = mgr.query(new DownloadManager.Query().setFilterById(lastDownload));
            if(c.moveToFirst()){
                int x = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
                switch(x){
                case DownloadManager.STATUS_PAUSED:
                case DownloadManager.STATUS_PENDING:
                case DownloadManager.STATUS_RUNNING:
                    break;
                case DownloadManager.STATUS_SUCCESSFUL:
                    loader.setVisibility(View.GONE);
                    break;
                case DownloadManager.STATUS_FAILED:
                    //TODO: retry download
                    break;
                }
            }

        }
    };

问题是,旋转轮仅在列表视图中单击的最后一个项目时隐藏。我尝试使用调试模式,但程序具有正确的行为(意味着loader.setVisibility(View.GONE)每次下载都会调用)。我不知道为什么除了最后点击的项目之外,旋转轮不会隐藏。


EDIT : 3我知道为什么除了最后点击的项目之外,旋转轮不会隐藏。

当我单击多个项目时,lastDownload 会获取最后一个单击的项目的 ID。因此,在广播接收器中,它执行的是最后单击的项目乘以单击的项目数的情况。
我尝试将lastDownload更改为长数组/表,并将其与referenceId进行比较,我相信它是意图中包含的id。
这是新代码(y=0,ld 是单击的项目数):

BroadcastReceiver onComplete = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) { 
            long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
            if(y <ld){
                if(lastDownload[y] == referenceId){

            Cursor c = mgr.query(new DownloadManager.Query().setFilterById(lastDownload[y]));
            if(c.moveToFirst()){
                int x = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
                switch(x){
                case DownloadManager.STATUS_PAUSED:
                case DownloadManager.STATUS_PENDING:
                case DownloadManager.STATUS_RUNNING:
                    break;
                case DownloadManager.STATUS_SUCCESSFUL:
                    loader.setVisibility(View.GONE); // This loader is the one of the last item clicked
                    break;
                case DownloadManager.STATUS_FAILED:
                    //TODO: retry download
                    break;
                }

            }

                       y=y+1;

                   }
            }   
        }
    };

我没有编写将变量放回 0 的部分,但目前代码几乎按预期工作。剩下的唯一问题是我消失的旋转轮是最后单击的项目的旋转轮。我知道为什么。因为这一行:loader = ((ProgressBar) view.findViewById(R.id.spinWheel2));位于onItemClicked方法。我认为我不能把它放在其他地方,因为它所在的视图不是活动的视图。

长话短说:我必须找到一种方法来访问我单击的项目/视图的进度栏,因为我知道我可以在第一个项目到达广播接收器之前单击多个项目。


EDIT : 4好的,我这样做了:

y,z, and ld被设置为0一开始。

当单击某个项目时:

// Loader of the clicked item is made visible
loader[z].setVisibility(View.VISIBLE);

// Construction of the URL
SharedPreferences codeSaveUrl = getSharedPreferences(PREFS_TEXT,Context.MODE_PRIVATE);
url2 = codeSaveUrl.getString("defaut", ""); // Organization code
uri = url10 + url2 + "&file=" + udl ;

// URL parse to URI
Uri myuri = Uri.parse(uri);

// Enqueue file to downloads, with notification. Storage of download id in a table
lastDownload[ld] = mgr.enqueue(new DownloadManager.Request(myuri)
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI |DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle(udl + ".pdf")
.setDescription("Téléchargement en cours")
.setDestinationInExternalPublicDir("/Protocols/", (udl+".pdf"))
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE));

// Increment variables for next downloads
ld=ld+1;
z=z+1;

广播接收器:

// Broadcast Receiver called when a download is finished
BroadcastReceiver onComplete = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        // referenceId is the download's id for which the method is called
        long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
        // If y (=0 at the beginning) is inferior to the number of downloads
        if(y <ld){
            // If the id of the download corresponds to the one for which the method is called
            if(lastDownload[y] == referenceId){
                // We define a cursor depending on the id
                Cursor c = mgr.query(new DownloadManager.Query().setFilterById(lastDownload[y]));
                if(c.moveToFirst()){
                    // Download status recovery
                    int x = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
                    switch(x){
                    // If download is paused, pending or running, we do nothing
                    case DownloadManager.STATUS_PAUSED:
                    case DownloadManager.STATUS_PENDING:
                    case DownloadManager.STATUS_RUNNING:
                        break;
                    // If file has successfully been downloaded, loader is hidden
                    case DownloadManager.STATUS_SUCCESSFUL:
                        loader[y].setVisibility(View.GONE); 
                        // Increment y to go to next download
                        y=y+1;
                        break;
                    // If download failed, it is retried
                    case DownloadManager.STATUS_FAILED:
                        //TODO: retry download
                        break;
                    }
                }
            }
        }
    }
};

工作正常,除非在下载大文件时单击小文件的项目。小文件优先,下载管理器不再遵循表格的顺序,导致加载轮不会消失。


EDIT : 5

我找到了一种方法来做我想做的事,请参阅我的答案。

感谢您的帮助。


好吧,我设法用 HashTable 做我想做的事情:

// HashTable to store download id's and loaders
Hashtable<Long, SyncedProgressBar> storeTable = new Hashtable<Long, SyncedProgressBar>();

在我的 onClickListener 方法中,之后loader[z] and lastDownload[ld]获取它们的值,我将它们放入 HashTable 中:(下载 id 将是键,加载器将是值)

// Storing download id and loader in HashTable
storeTable.put(lastDownload[ld], loader[z]);

在我的广播接收器的 onReceive 方法中,而不是这样做:

if(lastDownload[y] == referenceId)

我查看 HashTable 是否包含意图的下载 id:

if(storeTable.containsKey(referenceId))

我将正确的值放入加载程序中:

loader[y] = storeTable.get(referenceId);

然后我只需要把加载器的可见性设置为GONE我想要的地方。这个解决方案对我有用,但如果我发现新的东西,我会更新它。

这是我的新代码:

在 onClickListener 方法中:(此处未完成)

// Loader of the clicked item is made visible
loader[z].setVisibility(View.VISIBLE);

// Construction of the URL
SharedPreferences codeSaveUrl = getSharedPreferences(PREFS_TEXT,Context.MODE_PRIVATE);
url2 = codeSaveUrl.getString("defaut", ""); // Organization code
uri = url10 + url2 + "&file=" + udl ;

// URL parse to URI
Uri myuri = Uri.parse(uri);

// Enqueue file to downloads, with notification. Storage of download id in a table
lastDownload[ld] = mgr.enqueue(new DownloadManager.Request(myuri)
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI |DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle(udl + ".pdf")
.setDescription("Téléchargement en cours")
.setDestinationInExternalPublicDir("/Protocols/", (udl+".pdf"))
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE));

// Storing download id and loader in HashTable
storeTable.put(lastDownload[ld], loader[z]);

// Increment variables for next downloads
ld=ld+1;
z=z+1;

广播接收器:

// Broadcast Receiver called when a download is finished
BroadcastReceiver onComplete = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        // referenceId is the download's id for which the method is called
        long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
        // If y (=0 at the beginning) is inferior to the number of downloads
        if(y <ld){
            // If the HashTable contains the Key-download-id for which the method is called
            if(storeTable.containsKey(referenceId)){
                // Loader takes the value for the key
                loader[y] = storeTable.get(referenceId);
                // We define a cursor depending on the id
                Cursor c = mgr.query(new DownloadManager.Query().setFilterById(referenceId));
                if(c.moveToFirst()){
                    // Download status recovery
                    int x = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
                    switch(x){
                    // If download is paused, pending or running, we do nothing
                    case DownloadManager.STATUS_PAUSED:
                    case DownloadManager.STATUS_PENDING:
                    case DownloadManager.STATUS_RUNNING:
                        break;
                    // If file has successfully been downloaded, loader is hidden
                    case DownloadManager.STATUS_SUCCESSFUL:
                        loader[y].setVisibility(View.GONE); 
                        // Increment y to go to next download
                        y=y+1;
                        break;
                    // If download failed, it is retried
                    case DownloadManager.STATUS_FAILED:
                        //TODO: retry download
                        break;
                    }
                }
            }
        }
    }
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 DownloadManager 时 ListView 中的 Android ProgressBar 的相关文章

随机推荐

  • 使用 DOS 或 BIOS 显示字符

    翻翻拉尔夫 布朗的中断列表 我发现有很多不同的方法可以将文本字符输出到屏幕上 ROM BIOS API 提供以下功能 AH 09h 在光标位置写入字符和属性 AH 0Ah 仅在光标位置写入字符 AH 0Eh 电传打字机输出 AH 13h 写
  • 如何使用 MySQL 函数按属性删除 JSON 数组中的对象?

    假设存储在 MySQL 中的以下 JSONjson数据类型 users group manager userID a123 group employee userID a456 如何删除用户对象 userID a456 不知道它在数组中的位
  • MaxExpansionDepth 与最新的 webapi 和微风

    我最近将所有 nuget 包更新为 EF6 的最新版本 breeze 1 4 5 system web http odata 5 0 0 0 以及所有其他可用的好东西 现在 对于包含 x y z 这样的扩展的一个查询 我收到如下错误 A f
  • 哪里可以下载JMXMP?

    我想使用 VisualVM 通过 JMX 远程分析 Java 应用程序 由于它是经过 NAT 和防火墙保护的 EC2 实例 因此我无法使用默认的 RMI 方法 而需要使用必须首先下载的可选 JMXMP 扩展 注意 如果您想使用 JMXMP
  • 如何在不重新启动服务器的情况下停止 Jenkins 上不可阻挡的僵尸作业?

    我们的 Jenkins 服务器有一个作业已经运行了三天 但没有做任何事情 单击角落里的小 X 不会执行任何操作 控制台输出日志也不会显示任何内容 我检查了我们的构建服务器 该作业实际上似乎根本没有运行 有没有办法通过编辑某些文件或锁定或其他
  • ASP.NET 中的两种方式数据绑定

    假设我们有一个对象 class Entity public string ID get set public string Name get set 我想将属性绑定到页面上的两个文本框 如下所示
  • pandas concat 用 NaN 填充非对齐索引

    Problem 我连接了两个 int 类型系列 而我返回的数据帧是 float 类型 发生这种情况是因为该系列的索引未对齐 并且当发生串联时 pandas 用 NaN 填充空白 然而 NaN 被认为是浮点数 不幸的是 我的所有整数都随之转换
  • Java Forkjoin 与 ExecutorService - 何时使用哪个?

    我刚刚读完这篇文章 Java 5 ThreadPoolExecutor 相对于 Java 7 ForkJoinPool 有什么优势 并觉得答案不够直接 你能用简单的语言和例子解释一下 什么是权衡Java 7 的 Fork Join 框架和旧
  • 仅限 jQuery 和 ReactJS 动画

    我只需要使用 jQuery 动画 请不要提及过渡 这是我的代码库 var CommentForm React createClass componentWillUnmount function cb console log hiding j
  • 删除表的存储过程

    我创建了一个存储过程 如果数据库中存在表 它将删除该表 当使用 EXEC 运行存储过程时 出现以下错误 消息 203 级别 16 状态 2 程序 sp DropIfExists 第 13 行 名称 IF 存在 从 sys objects 中
  • MySQL 视图的替代结构。它是什么?

    我们一直在使用 phpmyadmin 4 导出数据库 数据库包含一些视图 并且在通常的 CREATE VIEW 命令之前 有一个带有注释 视图 viewName 的替代结构 的 CREATE TABLE 命令 为什么使用这种替代结构 注意
  • 在最新的 xcode 5 中单独添加到 Storyboard 中的 UIViewController 后看不到 UIView

    我已将 UIView 拖放到 xcode 5 中情节提要中的 UIViewController 它已添加 但我在情节提要中看不到 UIView 有人有解决办法吗 在以前版本的 xcode 中 我确实按照以下链接描述的过程进行了操作 http
  • matlab:KeyPressFcn和WindowKeyPressFcn之间的区别

    Matlab 文档定义为KeyPressFcn是 由图形窗口具有焦点时发生的按键调用的回调函数 类似地 定义WindowKeyPressFcn是 当图形窗口或其任何子窗口具有焦点时发生的按键调用的回调函数 据我了解 图形的子对象是轴 绘图对
  • 使用同一库的两个版本

    我正在开发一个 iOS 项目 其中包含另一家公司创建的静态库 该库包含旧版本的 AFNeworking 我没有任何源文件 现在我需要使用 afneworking 的更新 且 bug 较少 版本 但我不能在项目中两次包含同一个类 当然 因为所
  • 使部分内容可编辑无法删除

    我有一个 contentEditable Div 我希望能够 保护 其中的部分免遭删除 例如 我有一个 contentEditable DIV 其中有一个 img 标签 我希望永远不会被删除 但我需要在用户键入时保持图像周围的文本流 htt
  • Selenium WebDriver 无需等待页面加载即可进入页面

    我正在使用 python api 将一些 Selenium RC 测试转换为 Selenium WebDriver 在 Selenium WebDriver 中 我注意到driver get http 似乎要等待整个页面加载后再继续 有没有
  • 使用 NSExpression 时捕获 NSInvalidArgumentException 的正确方法[重复]

    这个问题在这里已经有答案了 我想验证用户创建的表达式 例如 2 2 5 7 或更复杂 我使用 NSExpression 类来解析和计算这个表达式 这是我的游乐场代码 import UIKit let string 2 2 var ex NS
  • Chart.js 2.0 中背景的可接受范围突出显示

    我正在使用 Chart js 2 0 2 beta 构建一个简单的折线图 我想突出显示图表背景的特定范围以突出显示 可接受的范围 Here s an example of what I m wanting to recreate via C
  • 使用 MinGW 设置 GLFW

    我正在尝试使用 GLFW 学习 OpenGL 但遇到了一些问题 这是我的 main cpp include
  • 使用 DownloadManager 时 ListView 中的 Android ProgressBar

    我有一个 ListView 其中每个项目代表一个 PDF 文件 当用户单击某个项目时 应用程序必须将文件下载到外部存储上 现在下载无法正常运行 但这不是问题所在 我想要一个进度条 旋转轮样式 在下载文件时出现在列表的每个项目旁边 我的问题是