使用DownloadManager时在ListView中显示Android ProgressBar

使用DownloadManager时在ListView中显示Android ProgressBar,android,android-listview,android-progressbar,download-manager,android-download-manager,Android,Android Listview,Android Progressbar,Download Manager,Android Download Manager,我有一个列表视图,其中每个项目代表一个PDF文件。当用户单击某个项目时,应用程序必须将该文件下载到外部存储器上。 现在下载无法正常工作,但这不是问题所在。我希望在下载文件时,在列表的每个项目旁边都显示一个ProgressBar,即纺车样式 我的问题是:我找不到如何使纺车出现。在下载管理器之前,我尝试了一个异步任务,纺车工作了 这是我的密码: CategoryActivity.java(列表视图的活动) 并补充说: BroadcastReceiver onComplete = new Broadc

我有一个列表视图,其中每个项目代表一个PDF文件。当用户单击某个项目时,应用程序必须将该文件下载到外部存储器上。 现在下载无法正常工作,但这不是问题所在。我希望在下载文件时,在列表的每个项目旁边都显示一个ProgressBar,即纺车样式

我的问题是:我找不到如何使纺车出现。在下载管理器之前,我尝试了一个异步任务,纺车工作了

这是我的密码:

CategoryActivity.java(列表视图的活动)

并补充说:

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

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

编辑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;
                }
            }

        }
    };
问题是,旋转滚轮仅隐藏listView中单击的最后一项。我尝试了调试模式,但程序的行为是正确的(即每次下载都调用
loader.setVisibility(View.go)
)。我不知道为什么纺车不会隐藏,除了最后点击的项目


编辑:3 我知道为什么纺车不会隐藏,除了最后一个项目点击

当我单击多个项目时,lastDownload将使用上次单击的项目的id。因此,在广播接收器中,最后一个点击的项目数乘以点击的项目数。
我尝试将lastDownload更改为一个长数组/长表,并将其与referenceId进行比较,我认为这是包含在意图中的id。
这是新代码(y=0,ld是单击的项目数):

广播接收机:

// 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;
                    }
                }
            }
        }
    }
};
//下载完成时调用广播接收器
BroadcastReceiver onComplete=新的BroadcastReceiver(){
公共void onReceive(上下文、意图){
//referenceId是为其调用方法的下载的id
long referenceId=intent.getLongExtra(DownloadManager.EXTRA\u DOWNLOAD\u ID,-1);
//如果y(=开始时为0)低于下载次数

如果(y我会使用一个异步任务,并使控制盘在onPreCreate&onPostCreate中出现/消失

private class MyDownloader extends AsyncTask<String, Void, File>{

    @Override
    protected void onPreExecute() {
        loader.setVisibility(View.VISIBLE);
    }

    @Override
    protected File doInBackground(String... params) {
        //Download and save file here, and return the result, which will be fed into the onPostExecute method
        return file;
    }

    @Override
    protected void onPostExecute(File file) {
        super.onPostExecute(file);
        loader.setVisibility(View.GONE);
    }
}
私有类MyDownloader扩展了异步任务{
@凌驾
受保护的void onPreExecute(){
loader.setVisibility(View.VISIBLE);
}
@凌驾
受保护的文件doInBackground(字符串…参数){
//在这里下载并保存文件,并返回结果,结果将被输入onPostExecute方法
返回文件;
}
@凌驾
受保护的void onPostExecute(文件){
super.onPostExecute(文件);
loader.setVisibility(View.GONE);
}
}

然后用new MyDownloader().execute(“linktopdf”)或类似的东西启动任务(您输入的.execute将被输入到doInBackground方法中)

请注意DownloadManager.enqueue是异步的,这意味着mgr.enque几乎立即返回,之后您当前的代码将微调器设置回不可见状态

要隐藏微调器,您必须注册广播接收器,以便在下载完成时接收通知。然后,您必须找到相应的微调器并将其隐藏。请注意,下载可能会失败(在这种情况下,仍会发送通知)


Commonware发布了一个演示如何使用DownloadManager的帖子。

好的,所以我设法用哈希表做了我想做的事情:

// HashTable to store download id's and loaders
Hashtable<Long, SyncedProgressBar> storeTable = new Hashtable<Long, SyncedProgressBar>();
在我的广播接收器的onReceive方法中,不要执行以下操作:

if(lastDownload[y] == referenceId)
我查看哈希表是否包含意图的下载id:

if(storeTable.containsKey(referenceId))
我在加载器中输入了正确的值:

loader[y] = storeTable.get(referenceId);
然后,我只需将加载程序的可见性放到我想要的位置即可。此解决方案对我有效,但如果发现新内容,我会更新它

这是我的新代码:

onClickListener方法中的(此处不完整)

广播接收器:

// 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;
                    }
                }
            }
        }
    }
};
//下载完成时调用广播接收器
BroadcastReceiver onComplete=新的BroadcastReceiver(){
公共void onReceive(上下文、意图){
//referenceId是为其调用方法的下载的id
long referenceId=intent.getLongExtra(DownloadManager.EXTRA\u DOWNLOAD\u ID,-1);
//如果y(=开始时为0)低于下载次数

如果(请注意,您必须在doInBackground内以同步方式下载文件,这样它将阻止异步任务。如果不能这样做,用户必须能够同时下载多个文件(或者单击多个文件,他们一次下载一个文件),并且必须能够在下载过程中执行其他操作。我已经尝试使用AsyncTask,但也存在纺车问题(有时不会消失,有时会在屏幕外的其他项目上克隆)添加了广播接收器。现在,当我单击相应的项目时,微调器可见,但其中一些在下载完成后仍然可见。我编辑了我的问题,但尚未实现下载失败案例。您的代码仅为最后单击的项目隐藏微调器。这是因为loader在onItemClick中获取其值。您必须存储由mgr.enqueue返回的下载id。broadcastreceiver中接收到的意图包含刚完成的下载id。使用此信息,您必须找到要禁用的微调器。好的,如果我像您提供的链接那样执行此操作,我可以将下载id存储在变量中,并使用
lastDownload=mgr.enqueue(…);
。然后在广播接收器中,我想我必须使用
setFilterById(lastDownload)
,但我不知道将
loader.setvisibility(View.GONE)
放在哪里。在这种情况下,您能提供完整的解决方案吗?我想执行类似的任务,但我想显示每次下载的进度和编号
// Storing download id and loader in HashTable
storeTable.put(lastDownload[ld], loader[z]);
if(lastDownload[y] == referenceId)
if(storeTable.containsKey(referenceId))
loader[y] = storeTable.get(referenceId);
// 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;
                    }
                }
            }
        }
    }
};