使用下载管理器时,在ListView中的Android ProgressBar



我有一个ListView,其中每个项目代表一个PDF文件。当用户单击一个项目时,应用程序必须将该文件下载到外部存储中。现在下载不能正常工作,但这不是问题所在。我想要一个进度条,纺轮样式,出现在列表的每个项目旁边,而文件下载。

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

下面是我的代码:

CategoryActivity.java (Activity of the 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);
    }
}

注意,如果我不让纺轮消失,它将始终在点击项目后可见。有了行来隐藏它,它甚至不会出现。


编辑:


我添加了一个BroadcastReceiver。

将这两行写入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;
                }
            }
        }
    };

问题是,转轮只隐藏在listView中单击的最后一个项目。我尝试了调试模式,但是程序有正确的行为(意味着每次下载都会调用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法中。我认为我不能把它放在其他任何地方,因为它所在的视图不是活动的视图。

长话短说:我必须找到一种方法来访问我点击的项目/视图的进度条,知道我可以在第一个到达Broadcast Receiver之前点击多个项目。


EDIT: 4我这样做了:

yzld开始设置为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]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;
                    }
                }
            }
        }
    }
};

请注意。Enqueue是异步的,它的意思是mgr。enqueue几乎立即返回,在此之后,当前代码将转轮设置为不可见。

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

CommonsWare发布了一个示例,展示了如何与DownloadManager一起工作。

我会使用AsyncTask,并使车轮出现/消失在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);
    }
}

然后使用new MyDownloader().execute("linktopdf")启动任务;之类的(你在。execute中输入的内容会被输入到doInBackground方法中)

相关内容

  • 没有找到相关文章

最新更新