RecyclerView上的进度指示器

问题描述 投票:1回答:1

我使用看起来像这样的RecyclerView

enter image description here

我使用AsyncTask来管理下载。我使用this按钮,以便卡列表中的每个项目可以具有相应下载的进度。我不知道如何向RecyclerView报告下载状态。如何将此更新发布到卡片上?

异步下载程序代码就是这样

public class DownloadFileFromURL extends AsyncTask<String, String, String> {

    private final String resourceType;

    public DownloadFileFromURL(String resourceType) {
        super();
        this.resourceType = resourceType;
        // do stuff
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        //showDialog(progress_bar_type);
    }

    protected void onProgressUpdate(String... progress) {
        // setting progress percentage
        // pDialog.setProgress(Integer.parseInt(progress[0]));
    }

    @Override
    protected String doInBackground(String... f_url) {
        int count;

        try {
            URL url = new URL(f_url[0]);
            String fileName = url.toString().substring(url.toString().lastIndexOf('/') + 1);
            URLConnection connection = url.openConnection();
            connection.connect();

            // this will be useful so that you can show a tipical 0-100%
            // progress bar

            int lengthOfFile = connection.getContentLength();
            Log.d("lengthofFile", String.valueOf(lengthOfFile));

            // download the file
            InputStream input = new BufferedInputStream(url.openStream(),
                    8192);

            String destinationDirectory ="";
            if(resourceType.equals(SyncUtil.IMAGE_ZIP)) {
                destinationDirectory= SyncUtil.TMP;
            }

            if(resourceType.equals(SyncUtil.VIDEOFILE)) {
                destinationDirectory = SyncUtil.VIDEO;
            }

            File mFolder = new File(AppController.root.toString() + File.separator+destinationDirectory);

            if (!mFolder.exists()) {
                mFolder.mkdir();
            }

            OutputStream output = new FileOutputStream(AppController.root.toString()+File.separator+destinationDirectory+File.separator
                    + fileName);

            byte data[] = new byte[1024];
            long total = 0;

            while ((count = input.read(data)) != -1) {
                total += count;
                // publishing the progress....
                // After this onProgressUpdate will be called
                publishProgress("" + (int) ((total * 100) / lengthOfFile));
                output.write(data, 0, count);
            }

            output.flush();

            // closing streams
            output.close();
            input.close();
            if(resourceType.equals(SyncUtil.IMAGE_ZIP)) {
                BusProvider.getInstance().post(new ZipDownloadComplete(fileName,resourceType));
            }

            if(resourceType.equals(SyncUtil.VIDEOFILE)) {

                   // BusProvider.getInstance().post(new VideoDownloadComplete(fileName));

            }
        } catch (Exception e) {
            Log.e("Error: ", e.getMessage());
        }

        return null;
    }

    @Override
    protected void onPostExecute(String file_url) {
    }
}

RecyclerView适配器在这里

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    final Video video = videosList.get(position);
    holder.title.setText(video.getTitle());
    holder.description.setText(video.getDescription());

    holder.downloadButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String url ="http://"+ AppController.serverAddr +":"+AppController.port +"/video/"+video.getUrl()+video.getExtension();
            DownloadFileFromURL downloadFileFromURL = new DownloadFileFromURL(SyncUtil.VIDEOFILE);
            downloadFileFromURL.execute(url,video.getTitle(),video.getDescription());

        }
    });

    holder.bind(video,listener);
}
java android android-recyclerview android-asynctask recycler-adapter
1个回答
3
投票

虽然它不是一个很好的解决方案,但在我的情况下,我得到了它的工作。我只想用一些示例代码片段分享我的想法。

我假设您使用ProgressBar显示下载进度。因此,在适配器中获取ProgressBar的实例,并将引用传递给AsyncTask

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    final Video video = videosList.get(position);
    holder.title.setText(video.getTitle());
    holder.description.setText(video.getDescription());

    holder.downloadButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String url ="http://"+ AppController.serverAddr +":"+AppController.port +"/video/"+video.getUrl()+video.getExtension();

            // Pass the progressBar here. You might have to set it as a final variable. 
            DownloadFileFromURL downloadFileFromURL = new DownloadFileFromURL(SyncUtil.VIDEOFILE, holder.progressBar);
            downloadFileFromURL.execute(url,video.getTitle(),video.getDescription());

        }
    });
    holder.bind(video,listener);
}

现在像这样修改AsyncTask的构造函数。

public DownloadFileFromURL(... , ProgressBar mProgressbar) {
    this.mProgressbar = mProgressbar;
    this.mProgressbar.setProgress(0);
    this.mProgressbar.setMax(100);
}

在你的onProgressUpdate中添加AsyncTask

protected void onProgressUpdate(Integer... values) {
    mProgressbar.setProgress(values[0]);
}

现在在你的doInBackground中计算文件大小并在下载一定量的文件后发布进度。

protected void doInBackground() throws IOException {
    try {
        // Establish connection
        URL url = new URL(fileUrl);
        HttpURLConnection connection = (HttpURLConnection) url
                .openConnection();
        connection.setDoInput(true);
        connection.connect();
        final String contentLengthStr = connection.getHeaderField("content-length");

        InputStream input = connection.getInputStream();
        String data1 = f.getPath();
        FileOutputStream stream = new FileOutputStream(data1);

        byte data[] = new byte[4096];
        int count;
        int progressCount = 0;

        while ((count = input.read(data)) != -1) {
            stream.write(data, 0, count);
            progressCount = progressCount + count;

            int progress = (int) (((progressCount * 1.0f) / Integer.parseInt(contentLengthStr)) * 10000);

            // Publish your progress here
            publishProgress(progress);
        }

        stream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

注意:传递视图的原始引用不是一个很好的解决方案。我宁愿在我的活动中设置一个BroadcastReceiver,并且会在publishProgress函数中发布具有特定项目位置的广播。因此,当在主要活动中收到广播时,我可以调用notifyDatasetChanged来获取列表中的进度效果。

© www.soinside.com 2019 - 2024. All rights reserved.