我有两门课。我的主活动和一个扩展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);
}
}
我通过使用线程和处理程序/消息使它工作。
步骤如下:
声明进度对话框
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();
}
这个答案可能晚了,但我想提到一些事情,当你的活动依赖于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);
}
}
试试这个:
public class SomAsyncTask extends AsyncTask<String, Integer, JSONObject> {
private CallBack callBack;
public interface CallBack {
void async( JSONObject jsonResult );
void sync( JSONObject jsonResult );
void progress( Integer... status );
void cancel();
}
public SomAsyncTask(CallBack callBack) {
this.callBack = callBack;
}
@Override
protected JSONObject doInBackground(String... strings) {
JSONObject dataJson = null;
//TODO query, get some dataJson
if(this.callBack != null)
this.callBack.async( dataJson );// asynchronize with MAIN LOOP THREAD
return dataJson;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if(this.callBack != null)
this.callBack.progress(values);// synchronize with MAIN LOOP THREAD
}
@Override
protected void onPostExecute(JSONObject jsonObject) {
super.onPostExecute(jsonObject);
if(this.callBack != null)
this.callBack.sync(jsonObject);// synchronize with MAIN LOOP THREAD
}
@Override
protected void onCancelled() {
super.onCancelled();
if(this.callBack != null)
this.callBack.cancel();
}
}
用法示例:
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Context _localContext = getContext();
SomeAsyncTask.CallBack someCallBack = new SomeAsyncTask.CallBack() {
@Override
public void async(JSONObject jsonResult) {//async thread
//some async process, e.g. send data to server...
}
@Override
public void sync(JSONObject jsonResult) {//sync thread
//get result...
//get some resource of Activity variable...
Resources resources = _localContext.getResources();
}
@Override
public void progress(Integer... status) {//sync thread
//e.g. change status progress bar...
}
@Override
public void cancel() {
}
};
new SomeAsyncTask( someCallBack )
.execute("someParams0", "someParams1", "someParams2");
}
我觉得下面的方法很简单。
我已经声明了一个回调接口
public interface AsyncResponse {
void processFinish(Object output);
}
然后创建异步任务来响应所有类型的并行请求
public class MyAsyncTask extends AsyncTask<Object, Object, Object> {
public AsyncResponse delegate = null;//Call back interface
public MyAsyncTask(AsyncResponse asyncResponse) {
delegate = asyncResponse;//Assigning call back interfacethrough constructor
}
@Override
protected Object doInBackground(Object... params) {
//My Background tasks are written here
return {resutl Object}
}
@Override
protected void onPostExecute(Object result) {
delegate.processFinish(result);
}
}
然后在活动类中单击按钮时调用异步任务。
public class MainActivity extends Activity{
@Override
public void onCreate(Bundle savedInstanceState) {
Button mbtnPress = (Button) findViewById(R.id.btnPress);
mbtnPress.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyAsyncTask asyncTask =new MyAsyncTask(new AsyncResponse() {
@Override
public void processFinish(Object output) {
Log.d("Response From Asynchronous task:", (String) output);
mbtnPress.setText((String) output);
}
});
asyncTask.execute(new Object[] { "Your request to aynchronous task class is giving here.." });
}
});
}
}
谢谢
容易:
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结果更改为不同的匹配类型,以便获得不同的对象。