AsyncTask가 별도의 클래스이기 때문에 OnPostExecute () 결과를 주요 활동으로 가져 오는 방법은 무엇입니까?


361

이 두 수업이 있습니다. 내 주요 활동과을 확장하는 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);

}       

}   

HelmiB가 설명한 것과 같은 인터페이스를 만들거나 로컬 브로드 캐스트 리시버를 만들 수 있습니다 여기에서 샘플 브로드 캐스트 리시버 구현을 볼 수 있습니다. wiki.workassis.com/android-local-broadcast-receiver
Bikesh M

관찰자 패턴을 사용하지 않는 이유는 무엇입니까?
JAAAY

답변:


750

쉬운:

  1. 선택 사항 인 interface클래스를 작성 String output하거나 리턴하려는 변수가 될 수 있습니다.

    public interface AsyncResponse {
        void processFinish(String output);
    }
  2. AsyncTask클래스로 이동하여 인터페이스 AsyncResponse를 필드로 선언 하십시오 .

    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
      public AsyncResponse delegate = null;
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
     }
  3. 주요 활동에서 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 responseString result다른 일치 유형에 다른 개체를 얻기 위해.


20
완전히 모든 것을 작성하고 답을 보았습니다 :) 여기에 똑같이 생각하십시오! +1. 또한이 방법으로 여러 가지가 AsyncTask의 결과를들을 수 있습니다!
Roloc

8
델리게이트가 null로 설정되어 nullpointer 예외가 발생했습니다.이를
지우

2
.net 개발자를위한 참고 사항 인 AutoResetEvents를 사용하여이를 달성 할 수 있으며 autoresetevents에 대한 Java 구현도 있지만 훨씬 깨끗합니다. 그건 그렇고 ProcessFinish 스레드는 안전합니까?
Syler

13
널 포인터를 얻는 모든 사람들을 위해 인터페이스를 asyncTask 클래스 생성자로 전달한 다음 변수에 할당 한 다음 해당 변수에서 processfinish ()를 호출하십시오. 참고로 허용되는 asnwer를 참조하십시오. stackoverflow.com/questions/9963691/…
Sunny

2
@Sunny 당신 말이 맞아 ... 또한, 우리는 async.delegate = this;에 대한 비동기 객체를 초기화해야합니다. 작업에 ..
Ninja_Coder

24

몇 가지 옵션이 있습니다.

  • 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
        ...
    }

두 번째 옵션 : 클래스가 아닌 경우 왜 생성자와 고통을 겪어야 static합니까? 그림자 fieldOrMethodMyActivity있거나 MyActivity.this.fieldOrMethod그림자가있는 경우 사용하십시오 .
TWiStErRob

@TWiStErRob 두 번째는 내부 클래스 MyAsyncTask아니라고 가정합니다 .
quietmint

1
아, 죄송합니다. private/ protected최상위 클래스는 허용되지 않으므로 static내부 클래스 가 아닌 것으로 생각했습니다 .
TWiStErRob


2
활동 참조를 유지하는 것도 메모리 누수입니다. 콜백 접근법은 이것보다 훨씬 낫습니다
OneCricketeer

19

아래 접근 방식이 매우 쉽다고 생각했습니다.

콜백에 대한 인터페이스를 선언했습니다

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.." });


            }
        });

    }



}

감사


17

이 클래스는 Main 클래스에서 시도 할 수 있습니다. 그것은 나를 위해 일했지만 다른 방법으로 메소드를 구현했습니다.

try {
    String receivedData = new AsyncTask().execute("http://yourdomain.com/yourscript.php").get();
} 
catch (ExecutionException | InterruptedException ei) {
    ei.printStackTrace();
}

2
이것이 문제로 OP에 도움이되는 이유를 설명해 주시겠습니까?
John Odom

3
그것은 나를 도왔다. @HelmiB의 답변과 같은 다른 방법으로 시도했지만 결과가 없습니다.
Nicu P

알겠습니다. 죄송합니다. AsyncTask 클래스를 호출 한 다음이 호출에 매개 변수를 넣어야합니다. AsyncTask는 3 가지 일반 유형으로 정의됩니다. 1 개의 params (서버 도메인 또는 기타 param) 2 progress (void 가능), 3 개의 결과. 이러한 모든 유형은 JSONObject 또는 문자열 또는 모든 데이터 유형일 수 있습니다. AsyncTask 클래스가 있으면 데이터를 보낼 위치를 정의해야합니다. 예 : asyncTask.execute ( " sampletargeturl.com"). get () ;
Nicu P

이 방법을 사용할 때 Logcat에 "I / Choreographer ﹕ Skip a 50 frames! 응용 프로그램이 기본 스레드에서 너무 많은 작업을 수행하고있을 수 있습니다."라는 경고가 표시됩니다. 이것을 다루는 방법? AsyncTask에서 리턴 될 때까지 UI가 정지됩니까?
Huy Do

@NicuP 당신은 전화하는 것을 잊었을 수도 있습니다. execute()내 답변을 참조하십시오. 나는 거기에 의견을 추가했습니다. 업데이트 된 답변을 확인하고 싶을 수도 있습니다. 도움이 되었기를 바랍니다.
HelmiB

16

이 답변은 늦을 수 있지만에 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);
    }
}

2
대단해! 눈에 띄지 않는 중요한 점.
HasH

6

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();

}`


6

AsyncTask를 호출 할 때 onPostExecute를 재정의하면 몇 줄로 할 수 있습니다. 다음은 예입니다.

new AasyncTask()
{
    @Override public void onPostExecute(String result)
    {
       // do whatever you want with result 
    }
}.execute(a.targetServer);

나는 그것이 당신에게 도움이되기를 바랍니다, 행복한 코딩 :)


그것은 나를 위해 작동하지 않습니다. onPostExecute메소드에 들어 가지 않습니다 .
Francisco Romero

4

사람들이 왜 그렇게 어렵게 만드는가?

이것으로 충분합니다.

비동기 작업에서 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");

}


}

이것은 나를 위해 작동합니다. 이해하기 쉽고 간단합니다. Java가 설계된 것을 사용하고 있다고 생각합니다. 감사. 추신 : 추가해야 @Override합니까?
Old Geezer

1
아니요. @Override는 주석 일뿐입니다. 그래서 당신은 자바 컴파일러에게 메소드를 오버라이드 할 계획이라고 말하고 있고 그렇지 않다면 정보를 얻습니다.
bugdayci

4

get()메소드 AsyncTask(또는 오버로드 된 get(long, TimeUnit))를 호출 할 수 있습니다 . 이 메소드는 AsyncTask작업이 완료 될 때까지 차단되며이 시점에서을 (를) 리턴합니다 Result.

비동기 작업 생성 / 시작과 get메서드 호출간에 다른 작업을 수행하는 것이 현명 할 것입니다 . 그렇지 않으면 비동기 작업을 매우 효율적으로 활용하지 못합니다.


1
downvoted vecause get ()은 메인 스레드를 차단합니다. 차단 될 경우 AsyncTask를 사용할 이유가 없습니다
GabrielBB

3

자신의 청취자를 작성할 수 있습니다. 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...
}

2

안녕 당신은 이런 식으로 만들 수 있습니다 :

  1. 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");
            }
        }
    }
  2. 주요 활동에 추가

    // 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();
       ...
     }

1

Activity 클래스에서 정적 멤버를 작성하십시오. 그런 다음onPostExecute

예를 들어, AsyncTask의 결과가 문자열 인 경우 활동에 공개 정적 문자열을 작성하십시오.

public static String dataFromAsyncTask;

그런 다음 onPostExecuteAsyncTask에서 기본 클래스를 정적 ​​호출하고 값을 설정하십시오.

MainActivity.dataFromAsyncTask = "result blah";


1
이 시나리오에서 메모리 누수 가능성은 무엇입니까?
antroid

0

스레딩 및 핸들러 / 메시지를 사용하여 작동시킵니다. 다음과 같은 단계 : 진행률 선언 대화 상자

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();
}

0

데이터를 위임하거나 제공 하려면 "프로토콜" 을 사용해야 합니다 AsynTask.

대리인 및 데이터 소스

델리게이트는 다른 객체를 대신하여 또는 프로그램에서 이벤트가 발생하면 다른 객체를 대신하여 작동하는 객체입니다. ( 애플 정의 )

프로토콜은 일부 동작을 위임하는 몇 가지 방법을 정의하는 인터페이스입니다.

여기 완전한 예가 있습니다 !!!


0

이 시도:

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");

    }

0

아마도 약간 오버 보드가되지만 실행 코드와 결과 모두에 대한 콜백을 제공했습니다. 분명히 스레드 안전을 위해 실행 콜백에서 액세스하는 내용에주의를 기울이고 싶습니다.

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);

0

당신이 이것을 통해 희망 읽어 보시기 바랍니다하지 않을 경우.

https://developer.android.com/reference/android/os/AsyncTask

결과 데이터의 특성에 따라 생각할 수있는 최상의 옵션을 선택해야합니다.

사용하는 것이 좋습니다 인터페이스

다른 옵션은 ..

  • AsyncTask 클래스가 결과를 사용하려는 클래스 내부에 정의되어 있으면 정적 전역 변수 또는 get () 을 사용하고 외부 클래스 ( 필요한 경우 휘발성 변수 ) 에서 사용하십시오 . 그러나 AsyncTask 진행 상황을 알고 있거나 적어도 작업을 완료했으며 결과가 전역 변수 / get () 메소드를 통해 사용 가능한지 확인해야합니다. 당신이 사용할 수 폴링을, onProgressUpdate (진행 ...) , 동기화 또는 인터페이스 (어떤 당신을 위해 이제까지 가장 적합한)

  • 결과가 sharedPreference 항목과 호환 가능하거나 메모리에 파일로 저장 되어도 괜찮다 면 백그라운드 작업 자체에서도 저장할 수 있고 onPostExecute () 메소드
    를 사용하여 결과를 사용할 수있을 때 알림을받을 수 있습니다. 기억.

  • 문자열이 충분히 작고 활동 시작과 함께 사용되는 경우. onPostExecute () 내에서 의도 ( putExtra () ) 를 사용할 수는 있지만 정적 컨텍스트는 다루기 가 안전하지 않습니다 .

  • 가능 하면 onPostExecute () 메소드에서 정적 메소드 를 호출 할 수 있으며 결과는 매개 변수입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.