我有两门课。我的主活动和一个扩展AsyncTask,现在在我的主活动中,我需要从AsyncTask中的OnPostExecute()获得结果。如何将结果传递给我的主活动?

下面是示例代码。

我的主要活动。

public class MainActivity extends Activity{

    AasyncTask asyncTask = new AasyncTask();

    @Override
    public void onCreate(Bundle aBundle) {
        super.onCreate(aBundle);            

        //Calling the AsyncTask class to start to execute.  
        asyncTask.execute(a.targetServer); 

        //Creating a TextView.
        TextView displayUI = asyncTask.dataDisplay;
        displayUI = new TextView(this);
        this.setContentView(tTextView); 
    }

}

这是AsyncTask类

public class AasyncTask extends AsyncTask<String, Void, String> {

TextView dataDisplay; //store the data  
String soapAction = "http://sample.com"; //SOAPAction header line. 
String targetServer = "https://sampletargeturl.com"; //Target Server.

//SOAP Request.
String soapRequest = "<sample XML request>";    



@Override
protected String doInBackground(String... string) {

String responseStorage = null; //storage of the response

try {


    //Uses URL and HttpURLConnection for server connection. 
    URL targetURL = new URL(targetServer);
    HttpURLConnection httpCon = (HttpURLConnection) targetURL.openConnection();
    httpCon.setDoOutput(true);
    httpCon.setDoInput(true);
    httpCon.setUseCaches(false); 
    httpCon.setChunkedStreamingMode(0);

    //properties of SOAPAction header
    httpCon.addRequestProperty("SOAPAction", soapAction);
    httpCon.addRequestProperty("Content-Type", "text/xml; charset=utf-8"); 
    httpCon.addRequestProperty("Content-Length", "" + soapRequest.length());
    httpCon.setRequestMethod(HttpPost.METHOD_NAME);


    //sending request to the server.
    OutputStream outputStream = httpCon.getOutputStream(); 
    Writer writer = new OutputStreamWriter(outputStream);
    writer.write(soapRequest);
    writer.flush();
    writer.close();


    //getting the response from the server
    InputStream inputStream = httpCon.getInputStream(); 
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(50);

    int intResponse = httpCon.getResponseCode();

    while ((intResponse = bufferedReader.read()) != -1) {
        byteArrayBuffer.append(intResponse);
    }

    responseStorage = new String(byteArrayBuffer.toByteArray()); 

    } catch (Exception aException) {
    responseStorage = aException.getMessage(); 
    }
    return responseStorage;
}

protected void onPostExecute(String result) {

    aTextView.setText(result);

}       

}   

当前回答

这个答案可能晚了,但我想提到一些事情,当你的活动依赖于AsyncTask。这将帮助您防止崩溃和内存管理。正如上面已经提到的,我们也称它们为回调。它们将作为一个通知器工作,但永远不会发送活动的强引用或接口总是使用弱引用在这些情况下。

请参考下面的截图,以了解如何导致问题。

正如你所看到的,如果我们用一个强引用启动AsyncTask,那么在我们获得数据之前,并不能保证我们的Activity/Fragment将是活的,所以在这些情况下使用WeakReference会更好,这也将有助于内存管理,因为我们永远不会持有我们的Activity的强引用,那么它将有资格在它扭曲后进行垃圾收集。

查看下面的代码片段,了解如何使用强大的WeakReference -

java接口,将作为一个通知器工作。

public interface MyTaskInformer {

    void onTaskDone(String output);

}

MySmallAsyncTask.java AsyncTask做长时间运行的任务,这将使用WeakReference。

public class MySmallAsyncTask extends AsyncTask<String, Void, String> {

    // ***** Hold weak reference *****
    private WeakReference<MyTaskInformer> mCallBack;

    public MySmallAsyncTask(MyTaskInformer callback) {
        this.mCallBack = new WeakReference<>(callback);
    }

    @Override
    protected String doInBackground(String... params) {

        // Here do whatever your task is like reading/writing file
        // or read data from your server or any other heavy task

        // Let us suppose here you get response, just return it
        final String output = "Any out, mine is just demo output";

        // Return it from here to post execute
        return output;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        // Here you can't guarantee that Activity/Fragment is alive who started this AsyncTask

        // Make sure your caller is active

        final MyTaskInformer callBack = mCallBack.get();

        if(callBack != null) {
            callBack.onTaskDone(s);
        }
    }
}

这个类用于在这个类上启动我的AsyncTask实现接口,并覆盖这个强制方法。

public class MainActivity extends Activity implements MyTaskInformer {

    private TextView mMyTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mMyTextView = (TextView) findViewById(R.id.tv_text_view);

        // Start your AsyncTask and pass reference of MyTaskInformer in constructor
        new MySmallAsyncTask(this).execute();
    }

    @Override
    public void onTaskDone(String output) {

        // Here you will receive output only if your Activity is alive.
        // no need to add checks like if(!isFinishing())

        mMyTextView.setText(output);
    }
}

其他回答

嗨,你可以做这样的东西:

Create class which implements AsyncTask // TASK public class SomeClass extends AsyncTask<Void, Void, String>> { private OnTaskExecutionFinished _task_finished_event; public interface OnTaskExecutionFinished { public void OnTaskFihishedEvent(String Reslut); } public void setOnTaskFinishedEvent(OnTaskExecutionFinished _event) { if(_event != null) { this._task_finished_event = _event; } } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(Void... params) { // do your background task here ... return "Done!"; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); if(this._task_finished_event != null) { this._task_finished_event.OnTaskFihishedEvent(result); } else { Log.d("SomeClass", "task_finished even is null"); } } } Add in Main Activity // MAIN ACTIVITY public class MyActivity extends ListActivity { ... SomeClass _some_class = new SomeClass(); _someclass.setOnTaskFinishedEvent(new _some_class.OnTaskExecutionFinished() { @Override public void OnTaskFihishedEvent(String result) { Toast.makeText(getApplicationContext(), "Phony thread finished: " + result, Toast.LENGTH_SHORT).show(); } }); _some_class.execute(); ... }

我通过使用线程和处理程序/消息使它工作。 步骤如下: 声明进度对话框

ProgressDialog loadingdialog;

创建一个函数,在操作结束时关闭对话框。

   private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        loadingdialog.dismiss();

    }
    };

编码你的执行细节:

 public void startUpload(String filepath) {
    loadingdialog = ProgressDialog.show(MainActivity.this, "Uploading", "Uploading Please Wait", true);
    final String _path = filepath;
    new Thread() {
        public void run() {
            try {
                UploadFile(_path, getHostName(), getPortNo());
                handler.sendEmptyMessage(0);

            } catch (Exception e) {
                Log.e("threadmessage", e.getMessage());
            }
        }
    }.start();
}

容易:

Create interface class, where String output is optional, or can be whatever variables you want to return. public interface AsyncResponse { void processFinish(String output); } Go to your AsyncTask class, and declare interface AsyncResponse as a field : public class MyAsyncTask extends AsyncTask<Void, Void, String> { public AsyncResponse delegate = null; @Override protected void onPostExecute(String result) { delegate.processFinish(result); } } In your main Activity you need to implements interface AsyncResponse. public class MainActivity implements AsyncResponse{ MyAsyncTask asyncTask =new MyAsyncTask(); @Override public void onCreate(Bundle savedInstanceState) { //this to set delegate/listener back to this class asyncTask.delegate = this; //execute the async task asyncTask.execute(); } //this override the implemented method from asyncTask @Override void processFinish(String output){ //Here you will receive the result fired from async class //of onPostExecute(result) method. } }


更新

我不知道这是你们很多人的最爱。这是一个简单方便的界面使用方法。

仍然使用相同的界面。供参考,你可以把它合并到AsyncTask类中。

在AsyncTask类中:

public class MyAsyncTask extends AsyncTask<Void, Void, String> {

  // you may separate this or combined to caller class.
  public interface AsyncResponse {
        void processFinish(String output);
  }

  public AsyncResponse delegate = null;

    public MyAsyncTask(AsyncResponse delegate){
        this.delegate = delegate;
    }

    @Override
    protected void onPostExecute(String result) {
      delegate.processFinish(result);
    }
}

在你的活动课上做这个吗

public class MainActivity extends Activity {
  
   MyAsyncTask asyncTask = new MyAsyncTask(new AsyncResponse(){
    
     @Override
     void processFinish(String output){
     //Here you will receive the result fired from async class 
     //of onPostExecute(result) method.
     }
  }).execute();

 }

或者,再次在Activity上实现接口

public class MainActivity extends Activity 
    implements AsyncResponse{
      
    @Override
    public void onCreate(Bundle savedInstanceState) {

        //execute the async task 
        new MyAsyncTask(this).execute();
    }
      
    //this override the implemented method from AsyncResponse
    @Override
    void processFinish(String output){
        //Here you will receive the result fired from async class 
        //of onPostExecute(result) method.
    }
}

正如你可以看到上面的两个解决方案,第一个和第三个,它需要创建方法processFinish,另一个,方法在调用者参数中。第三种方法更加简洁,因为没有嵌套的匿名类。

提示:将String输出、String响应和String结果更改为不同的匹配类型,以便获得不同的对象。

在Activity类中创建一个静态成员。然后在onPostExecute期间分配该值

例如,如果你的AsyncTask的结果是一个字符串,在你的Activity中创建一个公共静态字符串

datfromasynctask;

然后,在AsyncTask的onPostExecute中,简单地对主类进行静态调用并设置值。

MainActivity。dataFromAsyncTask = "result blah";

您需要使用“协议”将数据委托或提供给AsynTask。

委托和数据源

委托是一个对象,当另一个对象在程序中遇到事件时,它代表另一个对象或与另一个对象协调行动。(苹果定义)

协议是定义一些方法来委托一些行为的接口。

这是一个完整的例子!!