2017-09-14 3 views
0

구성 변경 (특히 화면 선삭)을 수동으로 처리하도록 앱을 업데이트하려고합니다.Android : 스레드가 실행되는 동안 수동으로 구성 변경 사항을 처리하는 것에 관한 질문

스레드 실행 중에 변경 사항이 발생하면 어떻게되는지에 대한 질문이 있습니다.

주 스레드의 루퍼에 스레드와 처리기를 사용하여 스레드를 업데이트하여 주 스레드에 업데이트를 보내는 ThreadTask를 작성했습니다. 이것은 AsyncTask를 구현 한 것입니다.하지만 스레드를 사용하면 AsyncTask를 사용하는 것이 더 좋기 때문에 AsyncTask를 사용하는 것이 더 좋습니다.

public interface TaskObserver { 
    void pre_execute(); 
    void on_progress(ProgressData progress); 
    void finished(Object result); 
    void cancelled(Object result); 
} 

서브 클래스가 구현해야하는 추상 멤버

은 다음과 같습니다 :

abstract Object do_in_background(); 

일부 콘크리트

는 또한 위의 이벤트에 관찰자를 등록하는 두 가지 방법이있다,이 인터페이스를 사용 회원은 다음과 같습니다 :

synchronized void add_observer(TaskObserver observer){ 
    _observers.add(observer); 
} 

synchronized void remove_observer(TaskObserver observer){ 
    _observers.remove(observer); 
} 

synchronized void post_execute(Object result) { 
    int observers = _observers.size(); 
    for (int idx = 0; idx < observers; idx++) { 
     _observers.get(idx).finished(result); 
    } 
} 
///plus all the other methods of the interface 

그래서 구체적인 수업을 구현하면

public class MyThreadTask extends ThreadTask{ 

    @Override 
    Object do_in_background() { 
     progress.primary_max = 5; 
     for (int cur = 0 ; cur < 5 ; cur++) { 
      progress.primary = cur; 
      publish(); 
      Thread.Sleep(3000); 
     } 
    } 

} 

나는이과 같이 호출하는 활동 업데이트 :이 같은 mething

static final string TAG ="my_main_activity"; 

MyDataFragment _data; //this is a datafragment, a fragment with retaininstancestate , and a public `MyThreadTask task` variable 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    if (_data == null) { 
     _data = (MyDataFragment)getFragmentManager().findFragmentByTag(TAG + "_data"); 
     if (_data == null) { 
      _data = new MyDataFragment(); 
      getFragmentManager().beginTransaction().add(_data, TAG + "_data").commit(); 
     } 
    } 
    if (_data.task != null) { 
     _data.task.register(this); 
    } 
} 

@Override 
protected void onDestroy() { 
    super.onDestroy(); 
    if (_data.task != null) { 
     _data.task.remove(this); 
    } 
} 

이 내가하고자 할 때 항상 올바른 스레드

에 대한 참조가 있는지 확인합니다을 내가 그렇게하는 일을 시작해라.

button.setOnClickListener((v) -> { 
    if (_data.task != null) return; //to make sure only one thread starts at a time 
    _data.task = new MyThreadTask(); 
    _data.task.register(this); 
    _data.task.start(); //this is not thread's start, it is mine, it does other things too 
}) 

그리고 내가 끝내면 그것은 void f 내가 지금처럼 처리 inished (개체 결과) :

여기
void finished(Object result) { 
    try { 
     //get result; 
    } finally { 
     _data.task.remove(this); 
     _data.task = null; 
    } 
} 

내 질문은 :

가) 필요한 동기화로 내 관찰자 방법을 선언한다? 나는 그것을 확실히하기 위해 행동을했으나, 활동이 파괴되고 다시 만들어지면 같은 실에서 일어날까요? onDestroy 동안 관찰자가 제거되는 동안 progress_update가 발생할 수있는 기회가 있습니까?

b) 스레드가 완료되고 구성 변경 중에 post_execute (중요한)를 호출하면 어떻게됩니까? 업데이트가 손실됩니까?

c) 현재 관찰자가 없으므로 업데이트가 손실되는 경우 위의 처리 방법 중 하나가 구현되었거나 다른 방법일까요? 당신이 구성 변경을 통해 살아 백그라운드 작업을 계속

답변

0

선호하는 방법을 제공 할 수있는 모든 도움을 사전에

감사는 retained fragment에서 호스팅하는 것입니다. 단편의 동일한 인스턴스가 구성 변경을 통해 지속됩니다. 프래그먼트가 일시 중지되면 활동의 isChangingConfigurations을 확인하고 거짓 인 경우에만 작업을 취소하십시오.

어디서나 문서화되어 있는지 모르겠지만 전체 구성 변경 사항이 주 스레드에 게시되어 이전 활동을 일시 중지하고 새 활동을 다시 시작할 수없는 것으로 보입니다. 보관 된 조각에 AsyncTask을 사용했다면 구성 변경 중에 onPostExecute을 실행할 수 없었을 것입니다. 귀하의 접근 방식을 사용하면 관찰자가 없을 때 쉽게 완료 할 수 있습니다.

+0

, MyDataFragment의 _data는 유지 조각입니다. isChangingConfigurations 메서드를 주셔서 감사합니다. 아마도 도움이 될 것입니다. 또한 AsyncTask에 대한 정보를 주셔서 감사합니다. AsyncTask의 코드를 살펴보고 코드에서 해당 동작을 복제 할 수 있는지 확인해 보겠습니다. – Cruces

+0

AsyncTask의 코드를 확인한 결과, 특별한 문제는 없습니다. postexecute는 구성 변경 중에 실행됩니다. 간단한 데이터 핸들러를 사용하여 finish 데이터를 태스크에 게시하는 것으로 보입니다.이 태스크는 onpostexecute를 호출합니다. – Cruces

+0

@Cruces 'AsyncTask' 코드에 없습니다. 구성 변경의 모든 단계를 주 스레드와 함께 게시하는 것은 프레임 워크의 결과입니다. –

0

Asynctask는 잘 구성된 구성 변경 사항을 처리하지 않습니다. 내 생각에 Asynctask 대신을 쉽게 처리 할 수있는 synctaskLoader를 사용해야하며 activity/fragments의 수명주기 내에서 동작합니다.

당신은 AsyncTask를 실행하고 안드로이드 시스템 (설정을 변경하거나 메모리 보존시) 활동/조각을 죽이면 다음 doInBackground() 메소드는 여전히 백그라운드에서을 실행에 유지하고이 바람직하지 않은 결과가 발생할 수있는 경우.

따라서, 대신 AsyncTask를을 사용하는 당신은 AsynctaskLoader를 사용하거나 SQLite는 데이터를 채우는 경우 당신은 CursorLoader를 사용할 수 있습니다.

참고 : 나는이 유지 조각에서 호스팅하고

  1. Guideline to choose among AsyncTaskLoader and AsyncTask to be used in Fragment

  2. https://developer.android.com/reference/android/content/AsyncTaskLoader.html

+0

죄송합니다, 내가 AsyncTask의 구현을 말했을 때 미안해 할 수 있습니다, 나는 AsyncTask (pre_execute, do_in_background 등)와 같은 메소드를 가지고 있지만 스레드를 사용하여 백그라운드 스레드를 실행하고 Handler가 메인 스레드에 메시지를 보내도록했습니다. – Cruces

+0

또한 구현이 제대로 작동하고 올바르게 데이터를 업데이트하며 스레드가 완료되면 수명주기 메서드가 실행될 때 어떤 일이 발생하는지 궁금합니다 – Cruces

+0

구성 변경을 올바르게 처리하려면 AsyncTaskLoader를 사용하는 것이 좋습니다. 당신을 위해 변화. Android 워드 프로세서도 같은 것을 권장합니다. –