在onActivityResult()中启动Asynctask

时间:2016-11-29 15:32:35

标签: android android-asynctask onactivityresult

使用Intent.ACTION_GET_CONTENT的意图来选择XML文件。在onActivityResult()中,我启动了一个asynctask来将这个XML文件读入数据库。

我希望asynctask显示一个进度条,以确保在应用程序进行之前由于错误处理和预期的UI更改而完成。

只要执行了asynctask,就会显示intent创建的选择器对话框 - 即应用程序仍在onActivityResult()块中,并且没有显示progressdialog。 onPostExecute()被称为AFTER onActivityResult()结束。

我也尝试过使用.get()make asynctask在应用程序进行之前完成,但没有运气......

我认为这归结为错误的逻辑......

除了importDB是它自己的一个类之外,一切都在一个活动中发生。

意图就是这样开始......

intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/xml");
startActivityForResult(Intent.createChooser(intent, "Select XML"), RC_IMPORT_FILE);

...而onActivityResult()看起来像这样......

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (resultCode) {
        case Activity.RESULT_OK:
            switch (requestCode) {
                case RC_IMPORT_FILE:
                    Uri uri = data.getData();
                    if (data != null) {
                        importDB(new File(uri.toString()), uri, false);
                    };
                break;
        ... more switch statements...
    }
}

...而且importDB看起来像这样......

private void importDB(File file, Uri uri, boolean xmlRaw, Context context) {
    int error = 0;

    ImportDataBase importDataBase = new ImportDataBase();
    importDataBase.setContext(this);
    importDataBase.setUri(uri);
    importDataBase.xmlRaw(xmlRaw);
    try {
        importDataBase.execute("ImportDB").get();
    }   catch (ExecutionException ee) {
        logException(TAG, "importDB", ee);
        error = 1;
    }   catch (InterruptedException ie) {
        logException(TAG, "importDB", ie);
        error = 2;
    }
}

...而async任务(ImportDataBase)看起来像这样......

import android.app.ProgressDialog;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.widget.Toast;
import java.io.InputStream;

public class ImportDataBase extends AsyncTask<String, Integer, String> {

private static final String TAG = "ImportDataBase";

private Context context;
private ProgressDialog progressDialog;

private Uri uri = null;
private InputStream xmlStream = null;

private XMLParser xmlParser;
private boolean xmlRaw = true;
private int errorCode = 0;

public void xmlRaw(boolean xmlRaw) {
    this.xmlRaw = xmlRaw;
}

public void setUri(Uri uri) { this.uri = uri; }
public void setInputStream(InputStream inputStream) { this.xmlStream = inputStream; }
public void setContext(Context context) {
    this.context = context;
}

@Override
protected void onPreExecute() {
    super.onPreExecute();
    progressDialog = this.context;
    progressDialog.setCancelable(false);
    progressDialog.setMessage("Please wait...");
    progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    progressDialog.show();
    xmlParser = new XMLParser();
    xmlParser.xmlRaw(xmlRaw);
}

@Override
protected String doInBackground(String... params) { 
    String result = "0";
    int error = 0;
    InputStream inputStream = null;
    try {
        if (uri != null) inputStream = context.getContentResolver().openInputStream(uri);
            else inputStream = this.xmlStream;
    }   catch (Exception e) {
        result = "1000";
    }

    if (error == 0) {
        try {
            xmlParser.readXML(inputStream);
        }   catch (NullPointerException npe) {
                result ="10";
        }   catch (Exception e) {
                result ="10";
        }

    }   else result = "31"; 

    switch (xmlParser.getError()) {
        case 1 : result = "10"; break; // XML Parser error
        case 2 : result = "15"; break; // URLERROR;
        case 3 : result = "30"; break; // IOFileError
        case 4 : result = "31"; break; // FileError;
        case 5 : result = "32"; break; // FileDoesNotExists;
        default : result = "0";
    }

    try {
        inputStream.close();
    }   catch (Exception e) {
    }
    return result;
}

@Override
protected void onPostExecute(String string) {
    super.onPostExecute(string);
    String error = "";
    if (Integer.valueOf(string) > 0) {
        switch (Integer.valueOf(string)) {
            case 1:
                error = "You need to update the app to the newest version!";
                errorCode =1;
            break;
            case 10 :
                error = "XML parser error! Wrong file?";
                errorCode =10;
            break;
            case 15 :
                error = "Wrong URL!";
                errorCode =15;
            break;
            case 30 :
                error = "File read/Write error!";
                errorCode =30;
                break;
            case 31 :
                error = "File error";
                errorCode =31;
                break;
            case 32 :
                error = "File does not exsits!";
                errorCode =32;
                break;
            case 99 :
                error = "Unknwon XML parser error!";
                errorCode =99;
                break;
            case 100:
                error = "Database error! Retry or reinstall app!";
                errorCode =100;
            break;
            case 1000:
                error = "Unknown error!";
                errorCode =1000;
            break;
            default:
                error = "Unknwon error!";
        }
        Toast.makeText(context, error, Toast.LENGTH_SHORT).show();
    }   
    if ( progressDialog.isShowing() ) progressDialog.dismiss();
}

public int getError() {
    return this.errorCode;
}

@Override
protected void onCancelled() {
    super.onCancelled();
}
}

有关如何让应用程序等待asynctask完成的任何建议?在调用importDB()并希望显示进度条之前,是否可以在onActivityResult()内关闭对话框窗口?

1 个答案:

答案 0 :(得分:0)

基本上你应该从不阻止任何事情。我会使用AsyncTask在启动时显示ProgressDialog并在完成时隐藏它:

private ProgressDialog progressDialog;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   // blahblah
                    if (data != null) {
                        new ImportTask(new File(uri.toString()), uri).execute(); 
                    }
   // blahblah
}

class ImportTask extends AsyncTask<Void, Void, Void> {
  private File file;
  private Uri uri;

  ImportTask( File file, Uri uri ){
    this.file = file;
    this.uri = uri;
  }

  @Override
  protected void onPreExecute() {
    progressDialog.show();
  }

  @Override
  protected Void doInBackground( Void... voids ) {
    importDB(file, uri, false);
    return null;
  }

  @Override
  protected void onPostExecute( Void res ) {
    progressDialog.hide();
  }      
}

通过这种方式,您可以决定在importDB()正在运行期间并行执行其他操作。