2012-09-26 3 views
3

내 안드로이드 응용 프로그램에서 나는 Data 클래스를 가지고 있는데, 여기에는 download() 메서드가 포함되어있어 일부 데이터를 다운로드하고 구문 분석 할 수 있습니다. 이 작업이 완료되면 Observer이 통지됩니다.옵저버 및 스레드

또한 ActivityService입니다. ActivityAsyncTask을 사용하여 download() 메서드를 비동기로 호출합니다.

Service은 지속적으로 데이터를 처리하기 위해 업데이트를 수신 대기해야합니다. UI 스레드에서 발생하지 않아야합니다. 지금 내 질문

public class MyService extends Service { 

    @Override 
    public IBinder onBind(Intent arg0) { 
     return null; 
    } 

    @Override 
    public void onCreate() { 
     new MyWorkerThread().start(); 
    } 

    private class MyWorkerThread extends Thread implements Observer{ 

     @Override 
     public void run() { 
      observeData(); 
     } 

     private void observeData(){ 
      Data.getInstance().addObserver(this); 
     } 

      @Override 
      public void update(Observable observable, Object data) { 
       // In what thread does the code placed here run? 
      } 
    } 
} 

: 다음 Data 클래스의 download() 방법이 Observer들, 통지하면되는 스레드의 update() 방법은 실행을 나는이 작은 Service 클래스를 만들었습니다? 이것은 에 의해 생성 된 AsyncTask의 스레드에 있으며 서비스가 완료 될 때까지 코드가 onPostExecute() 방법을 통과하지 못하게합니까? 그렇다면 MyServiceObserver으로 만들고 매회 MyWorkerThread을 새로 만드는 것이 더 낫지 않습니까? 코드가 MyWorkerThread에 의해 자체 스레드에서 실행됩니까?

미리 감사드립니다.

+2

관찰자는 직접 메서드 호출입니다. 그래서'update'는'notifyObservers'를 호출하는 것으로 실행됩니다. 'run' 메쏘드가 거의 즉시 끝나기 때문에 스레드는 오랫동안 사라져 버렸습니다. – zapl

+0

좋습니다, 분명히 고마워요! 나는'notifyObservers' 메쏘드가 호출 될 때마다 새로운 쓰레드를 생성하는 것이 좋을 것이라고 생각합니다. – nhaarman

답변

1

당신에게 할 수는 있지만 그렇게 할 필요는 없습니다. 예를 들어 하나의 HandlerThread을 사용하면 동일한 결과를 얻을 수 있습니다. 또한 병렬로 실행되는 여러 스레드를 처리 할 필요가 없습니다.

public class ObserverService extends Service { 

    private Looper mLooper; 

    private void onDataChanged() { 
     // do whatever you need. 
     // This is executed in a background thread. 
    } 

    @Override 
    public void onCreate() { 
     HandlerThread ht = new HandlerThread("ObserverService"); 
     ht.start(); 
     mLooper = ht.getLooper(); 
     final Handler handler = new Handler(mLooper) { 
      @Override 
      public void handleMessage(Message msg) { 
       // executed in background HandlerThread 
       onDataChanged(); 
      } 
     }; 
     Observer observer = new Observer() { 
      @Override 
      public void update(Observable observable, Object data) { 
       // this is executed in whatever thread notifies 
       // enqueue max 1 messages. 
       handler.removeMessages(1234); 
       handler.sendEmptyMessage(1234); 
      } 
     }; 
     // register observer that send message to background thread. 
     Data.getInstance().addObserver(observer); 
    } 

    @Override 
    public void onDestroy() { 
     mLooper.quit(); 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     return Service.START_STICKY; 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 
} 
2

대답은

update 메소드가 호출되는 바와 같이, 데이터 클래스의 다운로드() 메소드가 관찰자 동일한 스레드에서

통지

합니다 (에있는 것이 바로 여기 download 메서드 실행과 동일한 스레드 - 이해할 수있는대로 해당 옵저버에 알립니다.

zapl이 게시됨에 따라 데이터를 관찰 한 후 MyWorkerThread이 완료됩니다 (observeData();).).

당신과 같이 작성해야 다른 스레드에서 실행하기 위해 : 나는 더 나은 매번 notifyObserver에 메소드가 호출되는 새로운 스레드를 만들 거라고 생각

private class MyWorkerThread extends Thread implements Observer{ 

    @Override 
    public void run() { 
     observeData(); 
    } 

    private void observeData(){ 
     Data.getInstance().addObserver(this); 
    } 

     @Override 
     public void update(Observable observable, Object data) { 
      this.start(); //will execute observeData(); in a new thread 
     } 
}