2014-10-05 3 views
15

저는 Android를 처음 사용하고 웹 개발에 익숙합니다. 자바 스크립트에서 당신은 당신이 함수를 인수로 전달하는 비동기 작업 (콜백)을 수행 할 때Android : AsyncTask에 함수 참조 전달

http.get('www.example.com' , function(response){ 
    //some code to handle response 
}); 
우리는 안드로이드의 AsyncTask와 동일한 작업을 수행 할 수 있는지 궁금

onPostExecute() 방법에 함수 참조를 전달 , 그리고 그것을 실행합니다.

제안 사항?

+0

어떻게 그런지 모르겠군요^_ ^. 비동기 작업을 사용하여 백그라운드 스레드를 만들고 코드 인 aka httprequest가 doInBackground() 메소드에 들어가고 이에 대한 returntype을 정의합니다. 백그라운드 작업이 완료되면 onPostExecute()가 호출되어 응답을 처리 할 코드를 작성하고 이제보기 및 모두를 업데이트합니다. 정의 된 진행 상황에 도달하면 트리거되는 progressupdate 메소드가 있습니다. 잠시 후에 설명서 링크를 얻을 수 있습니다. – Rico

+0

http://developer.android.com/reference/android/os/AsyncTask.html – Rico

답변

41

예 콜백 개념은 Java에도 매우 많이 존재합니다. 자바에서는이 같은 콜백을 정의

public interface TaskListener { 
    public void onFinished(String result); 
} 

하나는 종종 중첩이 같은 AsyncTask 내부 리스너 정의의 이러한 종류의 것입니다 :

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

    public interface TaskListener { 
     public void onFinished(String result); 
    } 

    ... 
} 

그리고 AsyncTask의 콜백의 완전한 구현이 보일 것이다 이와 같이 :

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

    public interface TaskListener { 
     public void onFinished(String result); 
    } 

    // This is the reference to the associated listener 
    private final TaskListener taskListener; 

    public ExampleTask(TaskListener listener) { 
     // The listener reference is passed in through the constructor 
     this.taskListener = listener; 
    } 

    @Override 
    protected String doInBackground(Void... params) { 
     return doSomething(); 
    } 

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

     // In onPostExecute we check if the listener is valid 
     if(this.taskListener != null) { 

      // And if it is we call the callback function on it. 
      this.taskListener.onFinished(result); 
     } 
    } 
} 

백그라운드 작업이 완료되면 바로 호출됩니다.

ExampleTask task = new ExampleTask(new ExampleTask.TaskListener() { 
    @Override 
    public void onFinished(String result) { 
     // Do Something after the task has finished 
    } 
}); 

task.execute(); 

아니면 같이 완전히 별도로 TaskListener을 정의 할 수 있습니다 : 당신은이 같은 모든 일을 사용할 수 있습니다

ExampleTask.TaskListener listener = new ExampleTask.TaskListener() { 
    @Override 
    public void onFinished(String result) { 
     // Do Something after the task has finished 
    } 
}; 

ExampleTask task = new ExampleTask(listener);  
task.execute(); 

또는이 같은 TaskListener 하위 클래스 :

public class ExampleTaskListener implements TaskListener { 

    @Override 
    public void onFinished(String result) { 

    } 
} 

을 그리고 다음과 같이 사용하십시오 :

ExampleTask task = new ExampleTask(new ExampleTaskListener());  
task.execute(); 

당신은 물론 단지 AsyncTaskonPostExecute() 메소드를 오버라이드 (override) 할 수 있지만, 실제로는 아주 나쁜 관행을 권장하고 대부분의 경우되지 않습니다. 예를 들어, 당신은이 작업을 수행 할 수 있습니다 :

ExampleTask task = new ExampleTask() { 
    @Override 
    public void onPostExecute(String result) { 
     super.onPostExecute(result); 

     // Your code goes here 
    } 
}; 

이 별도의 리스너 인터페이스 위의 구현으로 단지뿐만 아니라 작동하지만이에 몇 가지 문제가 있습니다 :

우선 무엇보다도 당신은 실제로 끊을 수있다 ExampleTask 모두 함께 위의 호출은 모두 super.onPostExecute()입니다. 개발자가 위와 같이 onPostExecute()을 덮어 쓰고 수퍼 전화를 포함시키지 않았거나 어떤 이유에서든 간단하게 삭제하는 것을 잊어 버린 경우 ExampleTask의 메소드는 더 이상 호출되지 않습니다. 예를 들어 TaskListener의 전체 리스너 구현은 콜백 호출이 onPostExecute()에 구현 된 이후 갑자기 더 이상 작동하지 않습니다. TaskListener을 무의식적으로 또는 무의식적으로 ExampleTask의 상태에 영향을 주어 여러 가지 다른 방법으로 깨뜨릴 수 있으므로 더 이상 작동하지 않습니다.

실제로 이와 같은 방법을 재정의 할 때 일어나는 일을 살펴보면 어떤 일이 벌어지고 있는지 훨씬 명확하게 알 수 있습니다.onPostExecute()을 재정 의하여 ExampleTask의 새 하위 클래스를 만듭니다.

public class AnotherExampleTask extends ExampleTask { 

    @Override 
    public void onPostExecute(String result) { 
     super.onPostExecute(result); 

     // Your code goes here 
    } 
} 

이 모든 것은 익명 클래스라는 언어 기능 뒤에 숨겨져 있습니다. 갑자기이 방법을 재정의하는 것은 더 이상 깨끗하지 않고 빠른 것으로 보이지 않습니다.

은 요약하면 :

  • 이 같은 방법은 실제로 새로운 서브 클래스를 생성 재정의. 당신은 단지 콜백을 추가하는 것이 아니라,이 클래스가 어떻게 작동 하는지를 수정하고 있고, 무의식적으로 많은 것을 깨뜨릴 수 있습니다.
  • 이와 같은 디버깅 오류는 a2의 단순한 고통 이상의 것일 수 있습니다. 갑자기 ExampleTaskExceptions을 던지거나 분명한 이유 때문에 더 이상 작동하지 않을 수 있기 때문에 실제로 코드를 수정하지 않았기 때문입니다.
  • 각 클래스는 적절하고 의도 된 위치에 리스너 구현을 제공해야합니다. 물론 onPostExecute()을 무시하여 나중에 추가 할 수는 있지만 항상 위험합니다. 그의 13k 평판을 가진 @flup조차도 자신의 대답에 super.onPostExecute() 전화를 포함하는 것을 잊어 버렸습니다. 숙련 된 개발자가 아닌 다른 사람들이 상상해보십시오!
  • 작은 추상화는 결코 누구에게도 해를 끼치 지 않습니다. 특정 수신기를 작성하는 것은 약간 더 많은 코드 일 수 있지만 훨씬 좋은 해결책입니다. 코드는보다 깨끗하고 읽기 쉽고 유지 보수가 용이합니다. onPostExecute()을 덮어 쓰는 것처럼 단축키를 사용하면 약간의 편의를 위해 코드 품질이 희생됩니다. 장기적으로는 문제를 일으키는 좋은 아이디어는 결코 아닙니다.
+0

이 답변은 일반적인 인터페이스 인 TaskListener 과 onFinished (T result)' –

+0

@ cricket_007 나는 그것을 개선이라고 부르지 않을 것이다. 각 태스크에는 엄격하게 정의 된 리스너가 있어야합니다. 유형 삭제를 무시할 때에도 다른 모든 것은 나쁜 설계 및 구현 문제로 이어지는 경향이 있습니다. –

+0

'String'응답만으로 제한하는 것보다 유연합니다.AsyncTask에서 콜백 방식을 사용하여 몇 가지 질문에 대답했습니다. [예를 들어] (http://stackoverflow.com/a/36105515/2308683), 당신은 나쁜 디자인으로 이어질 말? –

2

자바에서는 함수가 JavaScript보다 1 등급 시민보다 적습니다. AsyncTask는 클래스의 메서드로 콜백을 제공하며이를 재정의해야합니다.

웹 요청을하는 doInBackground의 구현과 함께 AsyncTask의 하위 클래스에 대해 Make an HTTP request with android을 참조하십시오.

다른 콜백을 사용하여 여러 HTTP 요청을 수행하려는 경우 RequestTask를 재정 의하여 다른 콜백 구현을 사용하여 onPostExecute를 구현할 수 있습니다. 당신은 자바 스크립트 콜백이 일반적으로 사용하는 폐쇄를 시뮬레이션하기 위해 익명 클래스를 사용할 수 있습니다 :

XAVER 보듯이
new RequestTask(){ 
    @Override 
    public void onPostExecute(String result) { 
     // Implementation has read only access to 
     // final variables in calling scope. 
    } 
}.execute("http://stackoverflow.com"); 

, 당신은 또한 청취자에 대한 완전한 인터페이스를 만들 수 있습니다. 이것은 몇 가지 기본 onPostExecute 함수를 구현하고 특정 호출에 대해 이러한 기본 구현 중 하나를 선택하려는 경우 유용합니다.

+0

'onPostExecute()'를 이렇게 오버라이드하는 것은 거의 좋은 생각이 아닙니다. 클래스는 적절하고 의도 된 곳에서 리스너 기능을 제공해야합니다. 당신이하고있는 일은 여러면에서 위험합니다. 왜냐하면 대부분이'RequestTask'를 모두 망칠 수 있기 때문입니다. 내 대답의 하단 부분을 참조하십시오. –

+0

@XaverKapeller 사실, 슈퍼 클래스의'onPostExecute'는 일을하지 않고 매우 무의미합니다. 'onPostExecute' *는 콜백입니다. 당신이 몰래 연결할 수있는 내부 구현 메소드가 아닙니다. 그 목적은 작업의 원래 작성자에게 결과 통지입니다. – flup

+0

새로운'AsyncTask'를 구현하고 있다면 그렇습니다. 그렇지만 이미'RequestTask'에서 구현 된 기능을 깨뜨릴 수있는 것보다 당신의 답안에서'RequestTask'처럼'AsyncTask'를 이미 하위 클래스로 분류했다면 그렇습니다. 그것이 내가 이전에 언급 한 내용입니다. –