AsyncTask가 별도의 클래스이기 때문에 OnPostExecute () 결과를 주요 활동으로 가져 오는 방법은 무엇입니까?
이 두 수업이 있습니다. 내 주요 활동과를 확장하는 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);
}
}
쉬운:
선택 사항 인
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();
}
또는 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.
}
}
위의 첫 번째 솔루션과 세 번째 솔루션의 두 가지 솔루션을 볼 수 있듯이 method를 작성해야 processFinish하며 다른 하나는 caller 매개 변수 내에 있습니다. 세 번째는 중첩 된 익명 클래스가 없기 때문에 더 깔끔합니다. 도움이 되었기를 바랍니다
팁 : 변경 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 ... }
이 클래스는 Main 클래스에서 시도 할 수 있습니다. 그것은 나를 위해 일했지만 다른 방법으로 메소드를 구현했습니다.
try {
String receivedData = new AsyncTask().execute("http://yourdomain.com/yourscript.php").get();
}
catch (ExecutionException | InterruptedException ei) {
ei.printStackTrace();
}
아래 접근 방식이 매우 쉽다고 생각했습니다.
콜백에 대한 인터페이스를 선언했습니다
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.." });
}
});
}
}
감사
이 답변은 늦을 수도 있지만에 Activity의지 할 때 몇 가지 언급하고 싶습니다 AsyncTask. 충돌 및 메모리 관리를 방지하는 데 도움이됩니다. 위의 답변에서 이미 언급했듯이 interface콜백이라고도합니다. 그들은 정보원으로 일할 것이지만, 그런 경우에는 결코 강력한 참조를 보내 Activity거나 interface항상 약한 참조를 사용 하지 않습니다 .
이것이 어떻게 문제를 일으킬 수 있는지 알아 보려면 아래 스크린 샷을 참조하십시오.
우리 AsyncTask가 강력한 참조로 시작했는지 알 수 있듯이 데이터를 얻을 때까지 Activity/ 우리 Fragment가 살아있을 것이라는 보장이 없으므로 WeakReference그러한 경우 에 사용하는 것이 더 좋으며 우리가 결코 잡지 않을 메모리 관리에 도움이 될 것입니다 우리의 강력한 참조 Activity는 왜곡 후 가비지 수집 대상이 될 것입니다.
멋진 WeakReference를 사용하는 방법을 알아 보려면 아래 코드 스 니펫을 확인하십시오.
MyTaskInformer.java 정보원으로 작동하는 인터페이스입니다.
public interface MyTaskInformer {
void onTaskDone(String output);
}
MySmallAsyncTask.javaAsyncTask는 장기 실행 작업을 수행합니다 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이 클래스는 이 클래스 와이 필수 메소드 에서 AsyncTask구현 을 시작하는 데 사용됩니다 .interfaceoverride
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);
}
}
AsyncTask를 호출 할 때 onPostExecute를 재정의하면 몇 줄로 할 수 있습니다. 다음은 예입니다.
new AasyncTask()
{
@Override public void onPostExecute(String result)
{
// do whatever you want with result
}
}.execute(a.targetServer);
나는 그것이 당신에게 도움이되기를 바랍니다, 행복한 코딩 :)
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");
}
}
의 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;
그런 다음 onPostExecuteAsyncTask에서 기본 클래스를 정적 호출하고 값을 설정하십시오.
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.
대리인 및 데이터 소스
델리게이트는 프로그램에서 이벤트가 발생했을 때 다른 오브젝트를 대신하거나 그와 함께 동작하는 오브젝트입니다. ( 애플 정의 )
프로토콜은 일부 동작을 위임하는 몇 가지 방법을 정의하는 인터페이스입니다.
이 시도:
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");
}
아마도 약간 오버 보드가되지만 실행 코드와 결과 모두에 대한 콜백을 제공했습니다. 분명히 스레드 안전을 위해 실행 콜백에서 액세스하는 내용에주의를 기울이고 싶습니다.
AsyncTask 구현 :
public class AsyncDbCall<ExecuteType,ResultType> extends AsyncTask<ExecuteType, Void,
ResultType>
{
public interface ExecuteCallback<E, R>
{
public R execute(E executeInput);
}
public interface PostExecuteCallback<R>
{
public void finish(R result);
}
private PostExecuteCallback<ResultType> _resultCallback = null;
private ExecuteCallback<ExecuteType,ResultType> _executeCallback = null;
AsyncDbCall(ExecuteCallback<ExecuteType,ResultType> executeCallback, PostExecuteCallback<ResultType> postExecuteCallback)
{
_resultCallback = postExecuteCallback;
_executeCallback = executeCallback;
}
AsyncDbCall(ExecuteCallback<ExecuteType,ResultType> executeCallback)
{
_executeCallback = executeCallback;
}
@Override
protected ResultType doInBackground(final ExecuteType... params)
{
return _executeCallback.execute(params[0]);
}
@Override
protected void onPostExecute(ResultType result)
{
if(_resultCallback != null)
_resultCallback.finish(result);
}
}
콜백 :
AsyncDbCall.ExecuteCallback<Device, Device> updateDeviceCallback = new
AsyncDbCall.ExecuteCallback<Device, Device>()
{
@Override
public Device execute(Device device)
{
deviceDao.updateDevice(device);
return device;
}
};
그리고 마지막으로 비동기 작업을 실행합니다.
new AsyncDbCall<>(addDeviceCallback, resultCallback).execute(device);
'development' 카테고리의 다른 글
| PHP : array_filter ()를 사용하여 배열 키를 필터링하는 방법? (0) | 2020.03.04 |
|---|---|
| 트위터 부트 스트랩 navbar 고정 상단 겹치는 사이트 (0) | 2020.03.04 |
| SQL Server Management Studio 및 Transact SQL에서 GO를 사용하는 것은 무엇입니까? (0) | 2020.03.04 |
| 목록에서 모든 값을 제거 하시겠습니까? (0) | 2020.03.04 |
| 요청으로 파이썬에서 큰 파일 다운로드 (0) | 2020.03.04 |
