본문 바로가기

android/Android 코드

Lifecycle

Activity, Fragment 와 같은 생명 주기를 가진 컴포넌트들은 특정 상황이 되면 Android 프레임워크에서 자동으로 Lifecycle Callback 메서드를 호출해줍니다. Activity 의 각 Lifecycle Callback 메서드에 Log 를 찍어보면 현재 Lifecycle state 가 어떤 지 금방 확인할 수 있지만, 어떤 경로를 통해 Lifecycle 의 state 가 변경되는 지 코드를 통해 분석해보기로 했습니다.

 

아래의 Activity Lifecycle state 가 업데이트 되는 경로는 앱을 처음 실행하여 MainActivity 가 실행될 때의 경로를 확인한 것입니다.  ActivityThread 에서 관찰중인 Looper 에 새로운 Activity 를 실행해달라는 메시지가 등록되며, Looper 에서 메시지를 꺼내 메시지 종류에 따라 ActivityThread 의 적절한 메서드를 호출함으로써 Activity 생성과 Lifecycle state 업데이트 작업이 트리거 됩니다.

handleLaunchActivity(ActivityThread) → performLaunchActivity(ActivityThread)
→ callActivityOnCreate(Instrumentation) 
→ performCreate(Activity) → dispatchActivityPostCreated(Activity) 
→ onActivityPostCreated(ReportFragment) → dispatch(ReportFragment)
→ handleLifecycleEvent(LifecycleRegistry)

 

 

1. ActivityThread 의 performLaunchActivity() 메서드가 호출되면 매개변수로 전달된 ActivityClientRecord 인스턴스에서 Intent 인스턴스 내의 ComponentName 인스턴스를 통해 Activity 인스턴스를 생성합니다. 

Activity 인스턴스를 생성한 후 Instrumentation 인스턴스의 callActivityOnCreate() 메서드를 호출합니다.

 

(Activity 의 attach() 메서드 내에서 mUiThread 와 mMainThread 필드를 설정합니다.

mUiThread 는 Thread.currentThread() 로 설정하며, mMainThread 는 attach() 메서드의 2번째 매개변수인 ActivityThread 인스턴스입니다. 일반적으로 Main Thread 와 UI Thread 를 동의어로 이해하고 있지만 Activity 내부에서 Main Thread 는 UI 를 업데이트하는 Thread 인스턴스를 지칭하는 것이 아닌 Activity, Service 등 컴포넌트의 인스턴스를 생성하는 등의 작업을 하는 기반 클래스인 ActivityThread 클래스의 인스턴스를 지칭하는 것을 확인할 수 있었습니다.)

public final class ActivityThread {
	/**
	* 전달된 Intent 내의 Activity ComponentName 을 통해 Activity 인스턴스를 생성하고
	* 생성된 Activity 인스턴스에 Window, Theme 등 설정을 한 후
	* callActivityOnCreate() 메서드를 호출합니다.
	*/
	private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
		ComponentName component = r.intent.getComponent();
		
		try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);			
		}
		if (activity != null) {
			activity.attach(appContext, this, getInstrumentation(), r.token,
				r.ident, app, r.intent, r.activityInfo, title, r.parent,
				r.embeddedID, r.lastNonConfigurationInstances, config,
				r.referrer, r.voiceInteractor, window, r.activityConfigCallback,
				r.assistToken, r.shareableActivityToken);
				
			int theme = r.activityInfo.getThemeResource();
			if (theme != 0) {
				activity.setTheme(theme);
			}
			
			if (r.isPersistable()) {
				mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
			} else {
				mInstrumentation.callActivityOnCreate(activity, r.state);
			}
		}
	}
}

 

 

2. 매개변수로 전달받은 Activity 인스턴스의 performCreate() 메서드를 호출합니다.

icicle 인스턴스는 onCreate  등의 Lifecycle Callback 메서드에 전달되는 savedInstanceState Bundle 입니다.

public class Instrumentation {
	/**
	* Activity 클래스의 performCreate() 메서드를 호출합니다.
	*/
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }
}

 

 

3. Activity 계층 구조에서 Override 된 onCreate() 메서드를 호출합니다.

MainActivity onCreate() → FragmentActivity onCreate() → ComponentActivity onCreate() → Activity onCreate()

onCreate() 메서드 호출이 끝나면 dispatchActivityPostCreated() 메서드를 호출합니다.

public class Activity extends ContextThemeWrapper 
	final void performCreate(Bundle icicle) {
        performCreate(icicle, null);
    }
	
	/**
	* Activity 클래스 계층 구조의 Override 된 onCreate() 메서드를 호출합니다.
	*/
	final void performCreate(Bundle icicle, PersistableBundle persistentState) {
		if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
		
		dispatchActivityPostCreated(icicle);
	}
	
	private void dispatchActivityPostCreated(@Nullable Bundle savedInstanceState) {
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if (callbacks != null) {
            for (int i = 0; i < callbacks.length; i++) {
                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPostCreated(this,
                        savedInstanceState);
            }
        }
        getApplication().dispatchActivityPostCreated(this, savedInstanceState);
    }
}

 

 

4. ReportFragment 의 internal class 인 LifecycleCallbacks 의 onActivityPostCreated() 메서드가 호출되면

companion object 에 선언된 dispatch() 메서드를 호출합니다.

dispatch() 메서드 내에서는 ActivityThread 에서 생성한 Activity 인스턴스의 getLifecycle() 메서드를 호출하여 얻은 Lifecycle 인스턴스의 handleLifecycleEvent() 메서드를 호출하여 Activity 의 Lifecycle state 를 업데이트 합니다.

open class ReportFragment() : android.app.Fragment() {
	@RequiresApi(29)
    internal class LifecycleCallbacks : Application.ActivityLifecycleCallbacks {
		override fun onActivityPostCreated(
            activity: Activity,
            savedInstanceState: Bundle?
        ) {
            dispatch(activity, Lifecycle.Event.ON_CREATE)
        }
	}

	companion object {
		/**
		* ComponentActivity 클래스가 LifecycleOwner 인터페이스를 구현하였으므로 
		* ComponentActivity 인스턴스의 getLifecycle() 메서드를 호출하여 얻은 LifecycleRegistry 인스턴스의 handleLifecycleEvent() 메서드를 호출합니다.
		* 
		*/
		@JvmStatic
        internal fun dispatch(activity: Activity, event: Lifecycle.Event) {
            if (activity is LifecycleRegistryOwner) {
                activity.lifecycle.handleLifecycleEvent(event)
                return
            }
            if (activity is LifecycleOwner) {
                val lifecycle = (activity as LifecycleOwner).lifecycle
                if (lifecycle is LifecycleRegistry) {
                    lifecycle.handleLifecycleEvent(event)
                }
            }
        }
	}
}

 

 

open class LifecycleRegistry private constructor(
    provider: LifecycleOwner,
    private val enforceMainThread: Boolean
) : Lifecycle() {	
	/**
	* 해당 메서드가 Main Thread 에서 실행되었는지 확인한 후(해당 메서드는 ActivityThread 의 Main Thread 와 연결된 Main Looper 의 Message 를 통해 실행되었으므로 Main Thread 에서 실행된 메서드입니다.)
	* Lifecycle state 를 매개변수로 전달받은 Event 의 state 로 이동시킵니다.
	*/
	open fun handleLifecycleEvent(event: Event) {
        enforceMainThreadIfNeeded("handleLifecycleEvent")
        moveToState(event.targetState)
    }
	
	/**
	* current state 와 새로운 state 가 동일한지 검사하고, current state 가 INITIALIZED 이고 새로운 state 가 DESTROYED 인지 검사합니다.
	* current state 를 새로운 state 로 설정한 후 sync() 메서드를 호출합니다.
	* current state 가 DESTROYED 인 경우 Lifecycle 에 설정된 observer 인스턴스들이 등록된 observerMap 의 참조를 초기화합니다.
	*/
	private fun moveToState(next: State) {
        if (state == next) {
            return
        }
        check(!(state == State.INITIALIZED && next == State.DESTROYED)) {
            "no event down from $state in component ${lifecycleOwner.get()}"
        }
        state = next
        if (handlingEvent || addingObserverCounter != 0) {
            newEventOccurred = true
            // we will figure out what to do on upper level.
            return
        }
        handlingEvent = true
        sync()
        handlingEvent = false
        if (state == State.DESTROYED) {
            observerMap = FastSafeIterableMap()
        }
    }
	
	/**
	* 추가된 observer 들의 state 와 current state 가 동기화될 때 까지 while 문을 수행합니다.
	* current state 가 observerMap 에 가장 처음 추가된 observer 의 state 보다 작다면 backwardPass() 메서드를 호출합니다.
	* current state 가 observerMap 에 가장 최근 추가된 observer 의 state 보다 크다면 forwardPass() 메서드를 호출합니다.
	*/
	private fun sync() {
        val lifecycleOwner = lifecycleOwner.get()
            ?: throw IllegalStateException(
                "LifecycleOwner of this LifecycleRegistry is already " +
                    "garbage collected. It is too late to change lifecycle state."
            )
        while (!isSynced) {
            newEventOccurred = false
            if (state < observerMap.eldest()!!.value.state) {
                backwardPass(lifecycleOwner)
            }
            val newest = observerMap.newest()
            if (!newEventOccurred && newest != null && state > newest.value.state) {
                forwardPass(lifecycleOwner)
            }
        }
        newEventOccurred = false
    }
	
	/**
	* 가장 마지막에 처음 추가된 observer 와 가장 마지막에 추가된 observer 가 소유한 state 가 동일하며, 
	* current state 가 가장 최근에 추가된 observer 가 소유한 state 와 동일하면 state 가 동기화 되어있다고 판단합니다.
	*/
	private val isSynced: Boolean
        get() {
            if (observerMap.size() == 0) {
                return true
            }
            val eldestObserverState = observerMap.eldest()!!.value.state
            val newestObserverState = observerMap.newest()!!.value.state
            return eldestObserverState == newestObserverState && state == newestObserverState
        }
}

'android > Android 코드' 카테고리의 다른 글

setContentView  (1) 2023.12.26