我正在尝试使用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
答案 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();
}