Как получить результат OnPostExecute () в main activity, потому что AsyncTask является отдельным классом?
у меня есть два класса. Моя основная деятельность и расширяет AsyncTask
, теперь в моей основной деятельности мне нужно получить результат от OnPostExecute()
на AsyncTask
. Как я могу передать или получить результат своей основной деятельности?
вот примеры кодов.
моя основная деятельность.
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);
}
}
14 ответов
просто:
-
создать
interface
класса, гдеString output
является необязательным, или может быть, что переменные, которые вы хотите вернуть.public interface AsyncResponse { void processFinish(String output); }
-
перейти к вашей
AsyncTask
класс, и объявить интерфейсAsyncResponse
в поле :public class MyAsyncTask extends AsyncTask<Void, Void, String> { public AsyncResponse delegate = null; @Override protected void onPostExecute(String result) { delegate.processFinish(result); } }
-
в вашей основной деятельности вам нужно
implements
интерфейс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. } }
обновление
я не знал, что это такое любимец многих из вас. Так что вот простой и удобный способ использования interface
.
все еще используя то же самое interface
. К вашему сведению, вы можете объединить это в 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);
}
}
сделайте это в своем Activity
класс
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();
}
или, реализуя интерфейс на деятельности снова
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.
}
}
как вы можете видеть 2 решения выше, первый и третий, он должен создать метод processFinish
другие один метод внутри параметр звонящего. Третий более аккуратный, потому что нет вложенного анонимного класса. Надеюсь, это поможет
Совет: Change String output
, String response
и String result
для различных типов подходящих для того, чтобы получить различные объекты.
есть несколько вариантов:
-
гнездо
AsyncTask
класс, внутриActivity
класса. Предполагая, что вы не используете одну и ту же задачу в нескольких действиях, это самый простой способ. Весь ваш код остается неизменным, вы просто перемещаете существующий класс задач как вложенный класс внутри класса вашей активности.public class MyActivity extends Activity { // existing Activity code ... private class MyAsyncTask extends AsyncTask<String, Void, String> { // existing AsyncTask code ... } }
-
создайте пользовательский конструктор для вашего
AsyncTask
это берет ссылку на вашActivity
. Вы создадите экземпляр задачи с помощью что-то вродеnew MyAsyncTask(this).execute(param1, param2)
.public class MyAsyncTask extends AsyncTask<String, Void, String> { private Activity activity; public MyAsyncTask(Activity activity) { this.activity = activity; } // existing AsyncTask code ... }
Я чувствовал, что ниже подход очень простой.
я объявил интерфейс для обратного вызова
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);
}
}
затем вызывается асинхронная задача при нажатии кнопки в классе activity.
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.." });
}
});
}
}
спасибо
вы можете попробовать этот код в ваш основной класс. Это сработало для меня, но я реализовал методы по-другому
try {
String receivedData = new AsyncTask().execute("http://yourdomain.com/yourscript.php").get();
}
catch (ExecutionException | InterruptedException ei) {
ei.printStackTrace();
}
вы можете сделать это в нескольких строках, просто переопределите onPostExecute при вызове AsyncTask. Вот вам пример:
new AasyncTask()
{
@Override public void onPostExecute(String result)
{
// do whatever you want with result
}
}.execute(a.targetServer);
надеюсь, это помогло вам, happy codding:)
в вашем Oncreate ():
`
myTask.execute("url");
String result = "";
try {
result = myTask.get().toString();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}`
почему люди делают это так трудно.
этого должно быть достаточно.
не реализуйте onPostExecute в асинхронной задаче, а реализуйте его в Activity:
public class MainActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState) {
//execute the async task
MyAsyncTask task = new MyAsyncTask(){
protected void onPostExecute(String result) {
//Do your thing
}
}
task.execute("Param");
}
}
этот ответ может быть поздно, но я хотел бы отметить несколько вещей, когда ваш Activity
зависит от AsyncTask
. Это поможет вам предотвратить сбои и управление памятью. Как уже упоминалось выше, ответы идут с interface
, мы также говорим им обратные вызовы. Они будут работать как информатор, но никогда не посылают сильный ссылка Activity
или interface
всегда использовать слабый ссылка в этих случаях.
пожалуйста, обратитесь к скриншоту ниже, чтобы найти как это может вызвать проблемы.
как вы можете видеть, если мы начали AsyncTask
С сильный ссылка тогда нет никакой гарантии, что наш Activity
/Fragment
будет жив, пока мы не получим данные, поэтому было бы лучше использовать WeakReference
в тех случаях, и это также поможет в управлении памятью, поскольку мы никогда не будем держать сильную ссылку нашего Activity
тогда он будет иметь право на сбор мусора после его искажение.
Проверьте ниже фрагмент кода, чтобы узнать, как использовать awesome WeakReference -
MyTaskInformer.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);
}
}
}
MainActivity.java
этот класс используется для запуска my AsyncTask
реализовать interface
на этом классе и override
этот обязательный метод.
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);
}
}
можно назвать get()
метод AsyncTask
(или перегруженных get(long, TimeUnit)
). Этот метод будет блокировать до AsyncTask
завершил свою работу, и в этот момент он вернет вам Result
.
было бы разумно выполнять другую работу между созданием / запуском вашей асинхронной задачи и вызовом get
метод, иначе вы не используете асинхронную задачу очень эффективно.
привет вы можете сделать что-то вроде этого:
-
создать класс, который реализует 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"); } } }
-
добавить в основной вид деятельности
// 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(); ... }
вы можете написать свой собственный слушатель. Это то же самое, что HelmiBответ, но выглядит более естественным:
создать интерфейс слушателя:
public interface myAsyncTaskCompletedListener {
void onMyAsynTaskCompleted(int responseCode, String result);
}
затем напишите асинхронную задачу:
public class myAsyncTask extends AsyncTask<String, Void, String> {
private myAsyncTaskCompletedListener listener;
private int responseCode = 0;
public myAsyncTask() {
}
public myAsyncTask(myAsyncTaskCompletedListener listener, int responseCode) {
this.listener = listener;
this.responseCode = responseCode;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
String result;
String param = (params.length == 0) ? null : params[0];
if (param != null) {
// Do some background jobs, like httprequest...
return result;
}
return null;
}
@Override
protected void onPostExecute(String finalResult) {
super.onPostExecute(finalResult);
if (!isCancelled()) {
if (listener != null) {
listener.onMyAsynTaskCompleted(responseCode, finalResult);
}
}
}
}
наконец реализовать прослушиватель в деятельности:
public class MainActivity extends AppCompatActivity implements myAsyncTaskCompletedListener {
@Override
public void onMyAsynTaskCompleted(int responseCode, String result) {
switch (responseCode) {
case TASK_CODE_ONE:
// Do something for CODE_ONE
break;
case TASK_CODE_TWO:
// Do something for CODE_TWO
break;
default:
// Show some error code
}
}
и вот как вы можете вызвать asyncTask:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Some other codes...
new myAsyncTask(this,TASK_CODE_ONE).execute("Data for background job");
// And some another codes...
}
создайте статический член в своем классе Activity. Затем назначьте значение во время onPostExecute
например, если результатом AsyncTask является строка, создайте общедоступную статическую строку в своей активности
public static String dataFromAsyncTask;
затем в onPostExecute
AsyncTask, просто сделайте статический вызов вашему основному классу и установите значение.
MainActivity.dataFromAsyncTask = "result blah";
Я заставляю его работать, используя поток и обработчик / сообщение. Шаги как следовать: Объявить Диалог выполнения
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();
}
вам нужно использовать "протоколы" делегировать или предоставлять информацию AsynTask
.
делегаты и источники данных
делегат-это объект, который действует от имени, или в координации с другим объектом, когда этот объект обнаруживает событие в программе. ( определение Apple)
протоколы-это интерфейсы, которые определяют некоторые методы для делегирования некоторых поведений.