下载大文件时,AsynTask仍在运行时,ProgrressDialog会出现混乱

|| 在实现AsynTask和ProgressDialog时,我有一个扼杀行为。当我下载小文件时,一切正常,进度状态从0%更新为100%。但是,当我下载较大的文件时,ProgressDialog上的数字将达到6或7%,然后不再更新。但是,在2,3分钟后,我收到一条消息,表明asyntask任务已完成下载过程。
public class DownloadHelper extends AsyncTask<String, Integer, Long> implements DialogInterface.OnDismissListener{

    private volatile boolean running = true;

    private PhonegapActivity _ctx = null;
    private ProgressDialog _progressDialog = null;
    private String _title = null;
    private File _root = null;
    private File _destination = null;
    private DatabaseHelper _dbHelper = null;

    private Cursor _cursorMedia = null;

    public DownloadHelper(String title, File root, File destination, DatabaseHelper dbHelper, PhonegapActivity ctx){
        _title = title;
        _ctx = ctx;
        _root = root;
        _destination = destination;
        _dbHelper = dbHelper;
    }

    @Override
    protected void onPreExecute() {
        if (_progressDialog != null)
        {
            _progressDialog.dismiss();
            _progressDialog = null;
        }
        _progressDialog = new ProgressDialog(_ctx);
        _progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        _progressDialog.setTitle(\"Downloading\");
        _progressDialog.setMessage(_title);
        _progressDialog.setCancelable(true);
        _progressDialog.setMax(100);
        _progressDialog.setProgress(0);
        /*_progressDialog.setOnCancelListener(
            new DialogInterface.OnCancelListener() { 
                public void onCancel(DialogInterface dialog) {
                    _progressDialog = null;
                    running = false;
                }
        });
        _progressDialog.setOnDismissListener(
            new DialogInterface.OnDismissListener() {
                public void onDismiss(DialogInterface dialog) {
                    Log.d(\"DownloadHelper\", \"canceled inside listener\");
                    _progressDialog = null;
                    running = false;
                }
            }
        );*/
        _progressDialog.show();

        running = true;
     }

    @Override
    protected Long doInBackground(String... sUrl) {
        try {
            Log.d(\"DownloadHelper\", \"Start download from url \" + sUrl[0]);
            long total = 0;
            total = _download(sUrl[0], _destination);

            return total;
        } catch (Exception ex2) {
            ex2.printStackTrace();
            Log.d(\"DownloadHelper\", \"Failed to download test file from \" + sUrl[0] + \" to \" + _destination.getAbsolutePath().toString());
            _closeProgressDialog();
        }
        return null;
    }

    protected void onCancelled(Long result) {
        Log.d(\"DownloadHelper\", \"CANCELLED result = \" + result);
        _closeProgressDialog();
    }

    protected void onProgressUpdate(Integer... progress) {
        if (_progressDialog != null && running)
        {
            Log.d(\"DownloadHelper\", \"UPDATED progess = \" + progress[0]);
            _progressDialog.setProgress(progress[0]);
        }
        else //cancel the task
        {
            Log.d(\"DownloadHelper\", \"onProgressUpdate cancelled\");
            cancel(true);
        }
    }

    protected void onPostExecute(Long result) {
        Log.d(\"DownloadHelper\", \"FINISHED result = \" + result);

        // Close the ProgressDialog
        _closeProgressDialog();
        running = false;

        if (result != null) //OK
        {
            _showAlertDialog(\"Test has been downloaded successfully.\", \"Message\", \"OK\");        
        }
        else // error
        {
            _showAlertDialog(\"Can not download the test. Please try again later.\", \"Error\", \"OK\");      
        }

    }

    @Override
    protected void onCancelled() {
        running = false;
    }    

    public void onDismiss(DialogInterface dialog) {
        Log.d(\"DownloadHelper\", \"Cancelled\");
        this.cancel(true);
    }


    protected void _closeProgressDialog(){
        if (_progressDialog != null)
        {
            _progressDialog.dismiss();
            _progressDialog = null;
        }
    }

    protected void _showAlertDialog(final String message, final String title, final String buttonLabel){
        AlertDialog.Builder dlg = new AlertDialog.Builder(_ctx);
        dlg.setMessage(message);
        dlg.setTitle(title);
        dlg.setCancelable(false);
        dlg.setPositiveButton(buttonLabel,
                new AlertDialog.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        dlg.create();
        dlg.show();     
    }

    protected Cursor _checkMedia() {

        _dbHelper.openDatabase(_destination.getAbsolutePath());
        Log.d(\"DownloadHelper\", \"Database is opened\");

        String[] columns = {\"type, size, location, location_id, url\"};
        Cursor cursor = _dbHelper.get(\"media\", columns);

        _dbHelper.closeDatabase();
        _dbHelper.close();
        _dbHelper = null;

        return cursor;
    }

    protected long _download(String sUrl, File destination) throws IOException {
        URL url = new URL(sUrl);
        URLConnection conexion = url.openConnection();
        conexion.connect();
        // this will be useful so that you can show a tipical 0-100% progress bar
        int lenghthOfFile = conexion.getContentLength();
        Log.d(\"DownloadHelper\", \"length of File = \" + lenghthOfFile);

        // downlod the file
        InputStream input = new BufferedInputStream(url.openStream());
        OutputStream output = new FileOutputStream(destination);

        byte data[] = new byte[1024];

        long total = 0;
        int count;

        // Reset the progress
        _progressDialog.setProgress(0);

        // Start downloading main test file
        while ((count = input.read(data)) != -1 && running) {
            total += count;
            Log.d(\"DownloadHelper\", \"total = \" + total);
            // publishing the progress....
            this.publishProgress((int)(total*100/lenghthOfFile));
            output.write(data, 0, count);
        }

        if (running == false)
        {
            this.cancel(true);
        }

        output.flush();
        output.close();
        input.close();

        return total;
    }
}
我还在onProgressUpdate()内添加了一条Log.d消息,调试消息一直显示到进度达到6或7%,然后控制台中再也没有任何反应了(但是该应用程序仍然可以正常工作,因为我没有收到任何错误消息,并且Gabrage Collector的消息仍显示在控制台中)。 这是我的代码 有人有什么问题吗? 已编辑 根据DArkO的建议,我将缓冲区大小更改为1MB,但仍然无法正常工作。我认为我的while循环出了点问题。我在while循环中使用log.d并在控制台中有一些类似的内容:
    D/DownloadHelper( 1666): length = **3763782**; total = 77356; percent = 2; save_percent = 0
    D/DownloadHelper( 1666): UPDATED progess = 2
    D/DownloadHelper( 1666): length = 3763782; total = 230320; percent = 6; save_percent = 0
    D/DownloadHelper( 1666): UPDATED progess = 6
    D/dalvikvm( 1666): GC freed 10241 objects / 1087168 bytes in 88ms
    *D/DownloadHelper( 1666): FINISHED result = **230320***
\“完成消息\”来自onPostExecute()。进度对话框停止后的1,2分钟后,出现此消息。如您所见,文件未完全下载。 我使用eclipse的调试工具调试了我的应用程序,我可以看到asynctask线程挂在此函数上
OSNetworkSystem.receiveStreamImpl(FileDescriptor, byte[], int, int, int) line: not available [native method]    
    
已邀请:
        您更新的频率太高,它无法及时显示更新,并且阻止了ui线程。 考虑使用带有postDelayed的处理程序来发送publishProgress更新,也许每秒或2。 或者,您可以增加缓冲区的大小,以使循环不会经常发生,现在,它具有1024个字节,因此可能只有0.5 MB或类似的大小,但是我仍然会使用处理程序方法。这样,您的更新和内存消耗就不会取决于进度更新。 编辑: 这是我用于我的项目之一的用于下载文件的代码。我已经用很大的文件(介于50和100 mb之间)测试了它,因此它肯定可以正常工作。试试看。
try {

        // this is the file to be downloaded
        final URL url = new URL(Url); // set the download URL, a url that
        // points to a file on the internet
        // create the new connection
        final HttpURLConnection urlConnection = (HttpURLConnection) url
                .openConnection();

        // set up some things on the connection and connect!
        urlConnection.setRequestMethod(\"GET\");
        urlConnection.setDoOutput(true);
        urlConnection.setConnectTimeout(4500); // Connection timeout in
        // miliseconds

        urlConnection.connect();
        Log.i(TAG, \"Connected\");
        // set the path where we want to save the file
        // in this case on root directory of the
        // sd card.
        File directory = new File(Environment.getExternalStorageDirectory().getAbsoluteFile()+MUSIC_VIDEOS_PATH+artist);
        // create a new file, specifying the path, and the filename
        // which we want to save the file as.

        directory.mkdirs(); // If we want to save the file in another
        // directory on the SD card
        // we need to make the directories if they dont exist.

        // you can download to any type of file ex: (image), (text file),
        // (audio file)
        Log.i(TAG, \"File Name:\" + filename);
        final File file = new File(directory, filename);
        if (file.createNewFile()) {
            file.createNewFile();
        }

        // this will be used to write the downloaded data into the file we
        // created
        final FileOutputStream fileOutput = new FileOutputStream(file);

        // this will be used in reading the data from the internet
        final InputStream inputStream = urlConnection.getInputStream();
        // this is the total size of the file
        final int totalSize = urlConnection.getContentLength();
        // variable to store total downloaded bytes
        int downloadedSize = 0;

        // a buffer
        final byte[] buffer = new byte[1024*1024];
        int bufferLength = 0; // used to store a temporary size of the
        // buffer
        int lastProgress = 0, progress = 0;
        // now, read through the input buffer and write the contents to the
        // file
        while ((bufferLength = inputStream.read(buffer)) > 0) {
            // add the data in the buffer to the file in the file output
            // stream (the file on the sd card
            fileOutput.write(buffer, 0, bufferLength);
            // add up the size so we know how much is downloaded
            downloadedSize += bufferLength;
            // this is where you would do something to report the prgress,
            // like this maybe
            // Log.i(\"Progress:\",\"downloadedSize:\"+String.valueOf((int)((downloadedSize/(double)totalSize)*100))+\" %  totalSize:\"+
            // totalSize) ;
            progress = (int) ((downloadedSize / (double) totalSize) * 100);
            if (progress != lastProgress && progress % 10 == 0) {
                notification.contentView.setProgressBar(R.id.ProgressBar01,
                        100, progress, false);
                // inform the progress bar of updates in progress
                nm.notify(id, notification);
                Log.i(TAG, String.valueOf(progress));
            }
            lastProgress = progress;
        }
        // close the output stream when done
        fileOutput.flush();
        fileOutput.close();
您会注意到我使用通知栏而不是进度栏来进行更新,但其余部分应该相同。     
        我同意更新的发生频率很高,但是我可能会使用一些简单的整数数学来编写类似以下内容的内容,而不是发布进度的处理程序对象。 它使用预先计算的tickSize(实际上是您想要显示进度更新的总大小的百分比),然后使用不太复杂的简单整数除法来跟踪何时显示下一个进度(使用2
int
而不是一个
Handler
对象)。
int lengthOfFile = conexion.getContentLength(); // note spelling :)
int tickSize = 2 * lengthOfFile / 100; // adjust to how often you want to update progress, this is 2%
int nextProgress = tickSize;

// ...

while ((count = input.read(data)) != -1 && running) {
    total += count;
    if (total >= nextProgress) {
        nextProgress = (total / tickSize + 1) * tickSize;
        this.publishProgress((int)(total*100/lengthOfFile));
    }
    output.write(data, 0, count);
}

// ...
    

要回复问题请先登录注册