如何在Android的AsyncTask中长时间运行XML解析时避免ANR?

时间:2013-02-07 07:45:04

标签: android android-asynctask

我从服务器下载文件,然后在本地数据库中解析和插入,而这个操作我正在使用进度条显示操作进度。由于文件非常大,因此需要2-4分钟进行解析我得到了ANR在进度条上,进度条在下载完成后没有得到更新它只显示50%的进度。如何避免这个ANR?我附上我的代码如下......

@Override
    protected void onPreExecute() 
    {
            flag = false;
            progressCount = 0;
            ProgressDialog progressBar = DdownoadProgressBar(context,
            progressCount);
            progressBar.show(); 

    }

    @Override
    protected Integer doInBackground(String... urls) {
        checkNetworkConnection();

        if (connectionFlag) {
            downloadFile1();
            progressCount = 1;
            publishProgress(progressCount);

            downloadFile2();
            progressCount = 2;
            publishProgress(progressCount);

            downloadFile3();
            progressCount = 3;
            publishProgress(progressCount);

            downloadFile4();
            progressCount = 4;
            publishProgress(progressCount);

            downloadFile5();
            progressCount = 5;
            publishProgress(progressCount);

            downloadFile6();
            progressCount = 6;
            publishProgress(progressCount);

            downloadflag = true;
        }
        return null;
    }


    @Override
    protected void onProgressUpdate(Integer... progress) 
    {
        Log.v(TAG, "In progressUpdate...");

        progressBar.setProgress(progressCount);

    }

    @Override
    protected void onPostExecute(Integer progress) {
        if (downloadflag) {
            try {

                Log.v(TAG, "Inside onPostExecute....");

                 parseFile1();
                 progressCount=7;
                 publishProgress(progressCount);

                 parseFile2();
                 progressCount=8;
                 publishProgress(progressCount);

                 parseFile3();
                 progressCount=9;
                 publishProgress(progressCount);

                 parseFile4();
                 progressCount=10;
                 publishProgress(progressCount);

                 parseFile5();
                 progressCount=11;
                 publishProgress(progressCount);

                 parseFile6();
                 progressCount=12;
                 publishProgress(progressCount);

                 progressBar.dismiss();
                 Toast.makeText(SynchronizeData.this,"Data is successfully downloaded from server.......", Toast.LENGTH_LONG).show();

            } catch (Exception e) {

                e.printStackTrace();
            }
        } else {

            progressBar.dismiss();

            Toast.makeText(
                    getApplicationContext(),
                    "File is not downloaded....Error in network connection...........",Toast.LENGTH_LONG).show();
            Log.v(TAG, "File is not downloaded...............");

        }
    }

5 个答案:

答案 0 :(得分:1)

将解析逻辑移动到doInBackground方法中。没有理由在后台线程上进行Web调用并在UI线程上进行解析。

答案 1 :(得分:1)

正如Rich所说:在doInBackground中解析文件。

其他选项是在onPostExecute中运行尽可能多的异步任务。

但是如果文件很大,你应该考虑使用thread / queue-worker模式/服务!

答案 2 :(得分:1)

是的,你正在做的非UI任务必须在doInBackground()方法中完成。 如果你将在主线程中运行的AsyncTask方法中执行一个长时间运行的任务,那么它将为你提供ANR。

答案 3 :(得分:1)

将解析逻辑移动到doinBackground(),如下面的代码。

@Override
protected void onPreExecute() 
{
        flag = false;
        progressCount = 0;
        ProgressDialog progressBar = DdownoadProgressBar(context,
        progressCount);
        progressBar.show(); 

}

@Override
protected Integer doInBackground(String... urls) {
    checkNetworkConnection();

    if (connectionFlag) {
        downloadFile1();
        progressCount = 1;
        publishProgress(progressCount);

        downloadFile2();
        progressCount = 2;
        publishProgress(progressCount);

        downloadFile3();
        progressCount = 3;
        publishProgress(progressCount);

        downloadFile4();
        progressCount = 4;
        publishProgress(progressCount);

        downloadFile5();
        progressCount = 5;
        publishProgress(progressCount);

        downloadFile6();
        progressCount = 6;
        publishProgress(progressCount);

        downloadflag = true;
    }

    if (downloadflag) {
        try {

             parseFile1();
             progressCount=7;
             publishProgress(progressCount);

             parseFile2();
             progressCount=8;
             publishProgress(progressCount);

             parseFile3();
             progressCount=9;
             publishProgress(progressCount);

             parseFile4();
             progressCount=10;
             publishProgress(progressCount);

             parseFile5();
             progressCount=11;
             publishProgress(progressCount);

             parseFile6();
             progressCount=12;
             publishProgress(progressCount);

        } catch (Exception e) {

            e.printStackTrace();
        }
    }
    return null;
}


@Override
protected void onProgressUpdate(Integer... progress) 
{
    Log.v(TAG, "In progressUpdate...");

    progressBar.setProgress(progressCount);

}

@Override
protected void onPostExecute(Integer progress) {

        try {

            Log.v(TAG, "Inside onPostExecute....");


             progressBar.dismiss();
             Toast.makeText(SynchronizeData.this,"Data is successfully downloaded from server.......", Toast.LENGTH_LONG).show();

        } catch (Exception e) {

            e.printStackTrace();
        }

}

答案 4 :(得分:0)

在使用AsyncTask之前,请阅读: Is AsyncTask really conceptually flawed or am I just missing something?

简单地说:从Activity的方法调用AsyncTask在概念上是有缺陷的,因为长操作可能比启动它的活动寿命更长。这样的操作应该是模型的责任(在MVC意义上),在这种情况下,它可能比AsyncTask更严重。