개발 관련/Android

ActivityLifecycleCallbacks 를 이용하여 실행중인 Activity 상태와 객체 가져오기.

snoworca 2015. 4. 9. 05:24


  Application 클래스 내부 메소드인 registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks)  를 이용해야 한다.

  이 메소드의 인자값으로 ActivityLifecycleCallbacks 를 상속받아 구현한 클래스의 인스턴스를 넣어준다.


  또는 다른 Activity 나 Service 내부에서


getApplication(). registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks {  ...  })


   와 같이 호출해 주는 방법도 있다. 


  registerActivityLifecycleCallbacks 을 더이상 사용하지 않을때는 unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks)  를 이용하여 이벤트 등록을 해지시켜 줘야 한다.


 registerActivityLifecycleCallbacks 는 Activity 의 라이프 사이클별로 발생하는 이벤트에 대한 콜백을 제공한다.

 즉, 어떤 Activity의 라이프 사이클 이벤트 메소드(onCreate, onDestroy, onResume, onPause, onStart, onStop 등) 가 호출되는 순간 때 외부에서 ActivityLifecycleCallbacks 를 사용하여 발생하는 이벤트와 대상 Activity 객체를 가져올 수 있다.


  사용시 주의할 점은 Activity 를 상속받아 구현된 당신의 액티비티 클래스에서 오버라이드된 이벤트 메소드가 끝나는 순간에 ActivityLifecycleCallbacks 의 이벤트가 호출되지 않을 수 있다. 좀 더 자세히 설명하기 위해서 아래 코드를 첨부한다.

  (말도 안 되는 코드지만, 이해를 돕기 위하여 이렇게 작성하였다.)


 <MainActivity.java>


  class MainActivity extends Activity {

  public ListView mTextView;


   protected void onCreate(Bundle savedInstanceState) { 

          super.onCreate(savedInstanceState);

          mTextView = (ListView)findViewById(R.id.textView);

   }

  ...



< ExActivityLifecycleCallbacks.java>


 class ExActivityLifecycleCallbacks implements ActivityLifecycleCallbacks {


  public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 

ListView textView = ((MainActivity)actvitiy). mTextView

// 이 곳에서 null 포인터 예외 발생. 

textView.setText("Hello World!");

  }  

 ... 


  이와 같이 에러가 발생하는 이유는 ActivityLifecycleCallbacks  의 onActivityCreated 가 실제로 호출되는 시점이 상속받은 액티비티의 onCreate 메소드에서 super.onCreate(savedInstanceState); 를 호출하는 순간이기 때문이다. 즉, ActivityLifecycleCallbacks 의 이벤트 메소드의 호출은 부모 Activity 클래스의 각 라이프 싸이클 관련 이벤트 메소드 내부에서 간접적으로 이루어지기 때문이다. 이 것에 대한 자세한 내용은 아래에서 다루겠다.



ActivityLifecycleCallbacks 의 메소드 이름을 보면 한 눈에 딱 들어오는 것이 쓰기에도 편하다.

api 레벨 14 (iCS) 이상에서 사용할 수 있다.

public class TestApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks);
    }

    ActivityLifecycleCallbacks mActivityLifecycleCallbacks = 

            new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState){ } @Override public void onActivityStarted(Activity activity) { } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } }; }





   하지만, 뭔가 되게... 찝찝한 것이 있다.  구글 개발자 사이트에서 ActivityLifecycleCallbacks 의 페이지를 찾아서 들어가보면 설명이 전혀 없는 것을 볼 수 있기 때문이다.  

  

(이 문서 페이지에 대하여 마지막으로 확인을 한 것은 이 포스팅을 작성한 시점과 동일한 15년 03월이다. 

이 문서에 대한 첫 확인은1년전에 했었다. 

지금까지는 변한 것이 없지만 앞으로는 개선될 수 있다.


  

  여담이지만, 그동안 구글 api 와 문서에 뒤통수 맞은 것이 한 두번이 아니다. 다행히 요즘은 많이 괜찮아 졌지만 오래전 안드로이드에서 버전별로 미묘하게 다르게 동작하는 AsyncTask 때문에 개삽질한 경험과,  Fragment 의 파편화, 기기별로 미묘하게 동작이 다른 onTouch 이벤트 등...

  (경험상 AsyncTask 파편화 처리가 최고 정점이었다. 결국 호환 클래스를 구현하여 해결하였지만 그 이후로 AsyncTask 는 두번다시 사용하지 않는다. ㅡ , , ㅡa )


그렇기 때문에 문서에 설명조차 없는 ActivityLifecycleCallbacks 사용이 조금 망설여 지는 것도 사실이다.

그러나 테스트 결과는 우려와는 다르게 정상적으로 동작하는 것을 확인 하였다. 


 Application.java 내부에서 ActivityLifecycleCallbacks이 사용되는 과정은 다음과 같다.


 우선 registerActivityLifecycleCallbacks 를 통하여 등록된 ActivityLifecycleCallbacks  인스턴스의 메소드들은 Application 클래스의 

dispatchActivityCreated, dispatchActivityStarted, dispatchActivity... 

 등의 메소드에서 호출된다. 

  참고로  이 메소드들은 2011년 7월에 추가된 것 같다.  (https://github.com/android/platform_frameworks_base/blob/3bdbf644d61f46b531838558fabbd5b990fc4913/core/java/android/app/Application.java)

 

  이 메소드들이 호출되는 장소는 Activity 클래스의 각 라이프 사이클 관련 이벤트 메소드다. 

  예를들어 Application dispatchActivityCreated 아래 코드와 같이 Activity 의 onCreate 이벤트 메소드에서 호출된다.


 ( Activity.java )


    protected void onCreate(@Nullable Bundle savedInstanceState) {

  // 나머지 코드는 생략.

  getApplication().dispatchActivityCreated(this, savedInstanceState);

    }


  API 문서에 설명이 없는 것은 조금 당황스럽지만, 안심하고 사용해도 될 것 같다.