使用 DownloadManager 时 ListView 中的 Android ProgressBar [英] Android ProgressBar in ListView while using DownloadManager

本文介绍了使用 DownloadManager 时 ListView 中的 Android ProgressBar的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 ListView,其中每个项目都代表一个 PDF 文件.当用户单击某个项目时,应用程序必须将文件下载到外部存储设备上.现在下载不能正常工作,但这不是问题.我希望在下载文件时在列表的每个项目旁边显示一个 ProgressBar,旋转轮样式.

I have a ListView in which each item represents a PDF file. When the user clicks on an item, the application must download the file on external storage. Now the download doesn't work properly, but that's not the question. I want a ProgressBar, spinning wheel style, to appear next to each item of the list while the file is downloaded.

我的问题是:我找不到如何让纺车出现.在下载管理器之前,我使用 AsyncTask 进行了尝试,并且旋转轮工作正常.

My problem is : I can't find how to make the spinning wheel appear. Before the Download Manager I tried it with an AsyncTask and the spinning wheel worked.

这是我的代码:

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);

    }
}

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

Note that if I don't make the spinning wheel disappear, it will always be visible after click on the item. With the line to hide it, it doesn't even appear.


我添加了一个广播接收器.

EDIT :
I added a BroadcastReceiver.

将这两行放在 onCreate() 中:

Put these two lines in 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);
    }

<小时>

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


EDIT 2 : Ok so here are some changes I made :

我将下载的 ID 保存在一个变量中:

I save the id of the download in a variable :

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));

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

Depending on the status of the download, I want to do different things :

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.GONE)).我不知道为什么除了最后点击的项目外,纺车不会隐藏.

The problem is, the spinning wheel only hides for the last item clicked in the listView. I tried with debug mode, but the program has a correct behavior (meaning loader.setVisibility(View.GONE) is called for every download). I don't know why the spinning wheel won't hide except for the last item clicked.

3我知道为什么除了最后点击的项目外,纺车不会隐藏.

EDIT : 3 I know why the spinning wheel won't hide except for the last item clicked.

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

When I click on multiple items, lastDownload takes the id of the last one clicked. So in the broadcast receiver, it does the case of the last item clicked times the number of items clicked.
I tried with changing lastDownload into an array/table of longs, and comparing it with referenceId, which I believe is the id contained in the intent.
Here is the new code (y=0 and ld is the number of items clicked):

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 方法中.我不认为我可以把它放在其他任何地方,因为它所在的视图不是活动的视图.

I didn't write the part where I put the variables back to 0, but for now the code pretty much works as expected. The only problem remaining is that the spinning wheel I make disappear is the spinning wheel of the last item clicked. And I know why. Because this line : loader = ((ProgressBar) view.findViewById(R.id.spinWheel2)); is located in the onItemClicked method. I don't think I can put it anywhere else because the view it is in is not the view of the activity.

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

Long story short : I must find a way to access the progress bar of the item/view I clicked on, knowing that I can click on multiple items before the first one reaches the Broadcast Receiver.

4 好吧,我这样做了:

yzld 在开头设置为 0.

y,z, and ld are set to 0 at the begining.

当一个项目被点击时:

// 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;
                    }
                }
            }
        }
    }
};

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

Works ok, except when an item of a small file is being clicked while a big file is being downloaded. The small file takes the priority and the download manager doesn't follow the order of the tables anymore, causing the loading wheel to not disappear.

5

我找到了做我想做的事情的方法,请参阅我的答案.

I found a way to do what I wanted, see my answer.

感谢您的帮助.

推荐答案

好的,所以我设法用 HashTable 做我想做的事 :

Ok so I managed to do what I wanted to do with a HashTable :

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

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

In my onClickListener method, after loader[z] and lastDownload[ld] take their value, I put them in the HashTable : ( the downloa id will be the key, the loader will be the value )

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

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

In my Broadcast Receiver's onReceive method, instead of doing this :

if(lastDownload[y] == referenceId)

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

I look if the HashTable contains the download id of the intent :

if(storeTable.containsKey(referenceId))

我在加载器中输入了正确的值:

And I put the correct value in the loader :

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

然后我只需要将加载程序的可见性放在我想要的 GONE 中.这个解决方案对我有用,但如果我发现新的东西,我会更新它.

Then I just have to put the loader's visibility to GONE where I want. This solution works for me, but I will update it if I find something new.

这是我的新代码:

在 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;
                    }
                }
            }
        }
    }
};

这篇关于使用 DownloadManager 时 ListView 中的 Android ProgressBar的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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