【问题标题】:ProgressBar is not updating while downloading a file in Android在 Android 中下载文件时 ProgressBar 未更新
【发布时间】:2013-01-25 19:05:35
【问题描述】:

我几乎阅读了所有类似的主题,但找不到解决方案。所以我决定问问自己。

我想下载一个文件并在操作过程中显示一个进度对话框。文件下载成功。

第一个问题是下载过程中进度条没有更新。它只是停留在 %0,下载完成后,对话框会按预期消失。

第二个问题是 - 我偶然注意到这一点 - 当我的活动得到更新(例如,当屏幕方向改变时)对话框消失但下载继续。

希望有人能帮忙。

这是我的代码:

package com.mehmetakiftutuncu.downloadunzipshow;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener
{
    final String LOG_TAG = "DownloadUnzipShow";

    final String RELATIVE_PATH = "mehmetakiftutuncu";
    final String FILE_NAME = "...";
    final String FILE_URL = "...";
    final String FULL_PATH = Environment.getExternalStorageDirectory().getPath() + "/" + RELATIVE_PATH + "/";;

    Button buttonDownload, buttonUnzip, buttonShow;
    ProgressDialog progressDialog;

    public class MyFileDownloader extends AsyncTask<String, String, String>
    {
        boolean isSuccessful = true;

        InputStream inputStream;
        OutputStream outputStream;

        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
            prepareProgressDialog();

            Log.d(LOG_TAG, "Downloading: " + FILE_URL + " to " + FULL_PATH + FILE_NAME);
        }

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

            try
            {
                URL url = new URL(params[0]);
                URLConnection connection = url.openConnection();

                connection.connect();

                int lengthOfFile = connection.getContentLength();

                File path = new File(FULL_PATH);
                if(!path.exists())
                {
                    path.mkdir();
                }

                inputStream = new BufferedInputStream(url.openStream());
                outputStream = new FileOutputStream(FULL_PATH + FILE_NAME);

                byte[] data = new byte[1024];

                long total = 0;
                int percentage = 0;

                while((count = inputStream.read(data)) != -1)
                {
                    total += count;

                    percentage = (int) ((total / lengthOfFile) * 100);

                    publishProgress(String.valueOf(percentage));

                    outputStream.write(data, 0, count);
                }

                outputStream.flush();
                outputStream.close();
                inputStream.close();
            }
            catch(Exception e)
            {
                isSuccessful = false;
                Log.e(LOG_TAG, "An error occured while downloading. Details: " + e.getMessage());
            }

            return null;
        }

        @Override
        protected void onProgressUpdate(String... values)
        {
            super.onProgressUpdate(values);

            progressDialog.setProgress(Integer.parseInt(values[0]));
        }

        @Override
        protected void onPostExecute(String result)
        {
            super.onPostExecute(result);

            if(isSuccessful)
            {
                Log.d(LOG_TAG, "File is successfully downloaded to: " + FULL_PATH + FILE_NAME);
            }

            progressDialog.dismiss();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        buttonDownload = (Button) findViewById(R.id.button_download);

        buttonDownload.setOnClickListener(this);
    }

    private void prepareProgressDialog()
    {
        progressDialog = new ProgressDialog(this);
        progressDialog.setTitle(getString(R.string.dialog_title));
        progressDialog.setMessage(getString(R.string.dialog_message) + FILE_URL);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog.setMax(100);
        progressDialog.setCancelable(false);
        progressDialog.show();
    }

    @Override
    public void onClick(View v)
    {
        switch(v.getId())
        {
            case R.id.button_download:
                new MyFileDownloader().execute(FILE_URL);
                break;
        }
    }
}

【问题讨论】:

  • 为什么要将 Integer 转换为 String 回 Integer?
  • 之前是整数 (AsyncTask) 但我尝试了很多东西。我认为这是我尝试过的愚蠢的事情之一。我不认为这是这里的问题,或者是吗? :)

标签: android download progress-bar progressdialog


【解决方案1】:

第一个问题是进度条在 下载操作。它只是停留在 %0 和下载时 完成后,对话框按预期消失。

这是因为行:

percentage = (int) ((total / lengthOfFile) * 100);

总是返回0,因为你正在做一个整数java除法,其中total小于lengthOfFile。将 total 设为 double 值。也不要将百分比转换为String,将AsyncTask 的第二个通用参数修改为Integer

第二个问题是 - 我偶然注意到了这一点 - 当我的活动 得到更新(例如,当屏幕方向改变时) 对话框消失,但下载继续。

在配置更改(例如轮换)时,Activity 将被重新创建,并在此过程中终止您的对话框。如果您想重新显示对话框,您需要通过将AsyncTask 传递给ActivityonRetainNonConfigurationInstance() 方法来在配置更改中保留AsyncTask(或者您可以使用片段)。在onCreate 方法中使用getLastNonConfigurationInstance 来查看您是否有任务保留并仍在运行并重新显示对话框。此外,您真的不应该将AsyncTask 设为Activity 中的内部类,因为您会将其与活动相关联。

【讨论】:

  • 将总变量更改为 double 类型解决了第一个问题,但似乎不推荐使用 onRetainNonConfigurationInstance() 方法。我现在要尝试这个解决方案来解决第二个问题:stackoverflow.com/a/14528795/1367813 感谢您的帮助。
  • @mAt 是的,它已被弃用,我推荐它,因为我不知道您是否与 Fragment API 联系过。你可以像下面的答案那样做,但如果你不小心,你可能会遇到麻烦。
  • 坦率地说,我对 Fragments 了解不多。按照以下答案中的建议,我也无法解决我的问题。您能否再解释一下如何使用您建议的方法(片段或上面的这些 b 方法)?
  • @mAt 我查看了一些我拥有的代码。看看这个gist.github.com/4637742
  • 您提供的代码解决了我的问题。我接受了答案。非常感谢你。 :)
【解决方案2】:

对话框消失了——你是在捕捉方向配置的变化,还是让 Android 来做?如果您让 Android 执行此操作,它将终止您的活动并重新创建它,这将破坏您的对话框。异步任务不会被杀死,因为异步任务归系统所有。要解决这个问题,请将 android:configChange="orientation" 添加到活动的清单中。一般的经验法则是,如果您想让对话在轮换中持续存在,您需要这样做。

【讨论】:

  • 目前 Android 处理它。我会尝试你建议的对话框消失。谢谢你。我仍然有进度问题。
  • 在 onProgressUpdate 中放一个日志或断点,看看它是否被调用。如果不是,请尝试在其中抛出一个 dialog.postInvalidate() 并查看它是否只是因为某种原因您没有重绘它。
  • 我的进度条按照这里的说明工作stackoverflow.com/a/14529136/1367813 但是,即使添加了 android:configChange="orientation" 我的对话框仍然消失。
  • 我的错,它的 configChanges 带有 s
猜你喜欢
  • 2017-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-10
相关资源
最近更新 更多