尝试在Asynctask中设置水平进度条会抛出NullPointerException

时间:2011-07-25 19:29:16

标签: android progress-bar android-asynctask

我正在尝试使用AsyncTask将{CSV}文件导出到SD卡,并使用ProgressBar告诉用户该任务是如何运行的。但是,当我尝试使用setProgress设置进​​度条时,我得到一个空指针异常。我的Logcat显示我传递的整数为8,因此它不是null。如果我注释掉我尝试设置进度条,它会正确运行。当我尝试设置进度条时,运行时看到的是什么?

完整的AsyncTask实现:

public class Exporter extends AsyncTask<File, Integer, Boolean> {
    private Context ctx;
    private final static String TAG = "Exporter";

    private ProgressDialog progress;

    private GeoDatabase db;
    private RecordListActivity parent;

    public Exporter(Context ctx) {
        super();
        Log.d(TAG, "Building " + this + " from " + ctx);
        this.ctx = ctx;
        parent = (RecordListActivity) ctx;
        db = (GeoDatabase) ctx.getApplicationContext();
    }

    @Override
    protected void onPreExecute() {
        // Initialize the progress dialog
        Log.i(TAG, "Pre-executing exporter");
        final String title = "Exporting";
        final String msg = "Initializing export...";
        progress = ProgressDialog.show(ctx, title, msg, true);
        progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

        super.onPreExecute();
    }

    /**
     * Begins operation of the exporter and determines if it was a
     * success.
     * 
     * @param args the destination file
     * 
     * @return whether the transfer was successful
     */
    @Override
    protected Boolean doInBackground(final File... args) {
        Log.d(TAG, "src-> " + "N/A" + ", dest-> " + args[0]);

        // Get the ArrayList of records inside the current folder
        ArrayList<Record> records = db.getRecordsIn(parent.getCurrentFolder());

        FileWriter writer;
        try {
            // Build a FileWriter targeting the destination
            writer = new FileWriter(args[0]);

            // Iterate through the records to write their CSV string out
            final int total = records.size();
            int current = 1;
            for (Record record : records) {
                Log.v(TAG, "Accessing " + record);
                writer.write(record.getCSVString() + "\n");
                Log.v(TAG, record.getCSVString());

                // Update the progress bar
                onProgressUpdate(total, current);
                current++;
            }

            // Close the writer
            writer.close();
            Log.d(TAG, "Writer closed");
        } catch (IOException e) {
            // Something has gone horribly wrong
            e.printStackTrace();
            Log.e(TAG, "Writing to file failed!");
            return false;
        }

        return true;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
            // values[1] is the current record being written
        // values[0] is the total number of records being written
        final int total = values[0];
        final int current = values[1];

        // Updates the text for the current record
        final String msg = "Writing record " + current + " of " + total;
        progress.setMessage(msg);
        Log.d(TAG, msg);

        // Updates the progress bar
        final int position = 100 * current / total;
        Log.d(TAG, "Setting position to " + position);
        progress.setProgress(position);
    }

    // can use UI thread here
    protected void onPostExecute(final Boolean success) {
        // TODO: Alert the user to success or failure - the dialog drops
        // to quickly now
        if (success) {
            progress.setMessage("Export successful");
            Log.i(TAG, "Export successful");
        } else {
            progress.setMessage("Export failed");
            Log.e(TAG, "Export failed");
        }
        progress.dismiss();
    }
}

完整的相关Logcat:

 24236     RecordListActivity  D  Export button pressed
 24236     RecordListActivity  D  Calling exporter to write out data
 24236     RecordListActivity  D  Building the dialog for exporting
 24236     RecordListActivity  D  OK clicked on export dialog
 24236               Exporter  D  Building edu.lafayette.cs.geology.Exporter@408dc328 from edu.lafayette.cs.geology.RecordListActivity@407ee0a0
 24236               Exporter  I  Pre-executing exporter
 24236               Exporter  D  src-> N/A, dest-> /mnt/sdcard/data.csv
 24236               Exporter  V  Accessing edu.lafayette.cs.geology.GeoDatabase$Bedding@408ea330
 24236               Exporter  V  1, 1311358183278,  latitude for bedding,  longitude for bedding, strike, dip, observed  a bedding , dip-direct
 24236               Exporter  D  Writing record 1 of 12
 24236               Exporter  D  Setting position to 8
 24236               dalvikvm  W  threadid=9: thread exiting with uncaught exception (group=0x401ab760)
 24236         AndroidRuntime  E  FATAL EXCEPTION: AsyncTask #1
 24236         AndroidRuntime  E  java.lang.RuntimeException: An error occured while executing doInBackground()
 24236         AndroidRuntime  E    at android.os.AsyncTask$3.done(AsyncTask.java:266)
 24236         AndroidRuntime  E    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
 24236         AndroidRuntime  E    at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
 24236         AndroidRuntime  E    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
 24236         AndroidRuntime  E    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
 24236         AndroidRuntime  E    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1081)
 24236         AndroidRuntime  E    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:574)
 24236         AndroidRuntime  E    at java.lang.Thread.run(Thread.java:1020)
 24236         AndroidRuntime  E  Caused by: java.lang.NullPointerException
 24236         AndroidRuntime  E    at android.app.ProgressDialog.onProgressChanged(ProgressDialog.java:346)
 24236         AndroidRuntime  E    at android.app.ProgressDialog.setProgress(ProgressDialog.java:207)
 24236         AndroidRuntime  E    at edu.lafayette.cs.geology.Exporter.onProgressUpdate(Exporter.java:114)
 24236         AndroidRuntime  E    at edu.lafayette.cs.geology.Exporter.doInBackground(Exporter.java:86)
 24236         AndroidRuntime  E    at edu.lafayette.cs.geology.Exporter.doInBackground(Exporter.java:1)
 24236         AndroidRuntime  E    at android.os.AsyncTask$2.call(AsyncTask.java:252)
 24236         AndroidRuntime  E    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
 24236         AndroidRuntime  E    ... 4 more

1 个答案:

答案 0 :(得分:1)

发现问题并解决方法here。它似乎是Android API中的known bug,其中使用ProgressDialog创建ProgressDialog.show(params)的工厂方法未正确设置更新处理程序。所以修改后的工作代码如下:

@Override
protected void onPreExecute() {
    // Initialize the progress dialog
    Log.i(TAG, "Pre-executing exporter");
    final String title = "Exporting";
    final String msg = "Initializing export...";
    progress = new ProgressDialog(ctx);
    progress.setTitle(title);
    progress.setMessage(msg);       
    progress.setIndeterminate(false);
    progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    super.onPreExecute();
}