【问题标题】:Launching an Asynctask within onActivityResult()在 onActivityResult() 中启动 Asynctask
【发布时间】:2016-11-29 15:32:34
【问题描述】:

使用带有 Intent.ACTION_GET_CONTENT 的意图来选择 XML 文件。在 onActivityResult() 中,我启动了一个异步任务来将此 XML 文件读入数据库。

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

只要执行异步任务,就会显示意图创建的选择器对话框 - 即应用程序仍在 onActivityResult() 块中,并且没有显示进度对话框。 onPostExecute() 在 onActivityResult() 结束后调用。

我也尝试使用 .get() 在应用程序继续之前完成异步任务,但没有运气......

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

一切都发生在一个活动中,除了 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;
    }
}

...异步任务(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();
}
}

关于如何让应用等待异步任务完成的任何建议?是否可以在调用 importDB() 之前关闭 onActivityResult() 中的对话框窗口并希望显示进度条?

【问题讨论】:

    标签: android android-asynctask onactivityresult


    【解决方案1】:

    基本上你应该从不阻止任何东西。我会使用 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() 运行期间并行执行其他操作。

    【讨论】:

    • 也许我有点不清楚。我试图显示一个进度条,但是由于在 asynctask 到达 onPostExecute() 之前,intent 创建的文件对话框窗口是打开的,因此在 onPreExecute 和 doInBackground() 期间永远不会显示进度条。有趣的是,progressbar.isShowing() 返回 true...
    • 不确定您的意思。通常以startActivityForResult() 打开的活动在onActivityResult 执行之前关闭
    • 我已经在模拟器 API 23 中尝试过这个,我的手机是带有 android 6 的三星 s6。我在 onActivityResult() 中调用的 asynctask 中的 doInBackground() 和在此睡眠期间会显示包含可供选择的文件的对话框。似乎活动/意图在 onAcitivtyResult() 完成后关闭...
    • 你为什么不在 OQ 中显示你的 AsyncTask?很奇怪,你在问一些东西,但除了你问的代码之外,什么都显示了......
    • 我也粘贴了异步任务。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-29
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多