Android 界面参数追踪工具类:通过生命周期回调监控传参

缘起
在界面跳转过程中,我们常常需要传递一些参数,例如埋点参数等可能需要一直向下传递的信息。然而,当界面跳转层级较深时,很容易出现中途忘记传递参数的情况。此时,如何高效排查参数传递问题就成为了一个关键需求。基于此,我想到可以开发一个工具类,实现界面跳转时参数的自动打印,以便于快速定位和解决参数传递过程中出现的问题。
缘灭
那么,如何具体实现这个工具类呢?熟悉 Android
开发的同学都知道,系统提供了 Application.ActivityLifecycleCallbacks
类,我们可以通过 context.registerActivityLifecycleCallbacks()
方法进行注册。借助该类的回调机制,能够监听到 Activity
的各个生命周期。我们的目标是在 onActivityCreated
回调中打印出上一个界面传递过来的参数,因为在这个回调中可以获取到 Activity
创建时的相关参数信息。
以下是
ActivityLifecycleCallbacks
接口的定义
public interface ActivityLifecycleCallbacks {
/**
* Called as the first step of the Activity being created. This is always called before
* {@link Activity#onCreate}.
*/
default void onActivityPreCreated(@NonNull Activity activity,
@Nullable Bundle savedInstanceState) {
}
/**
* Called when the Activity calls {@link Activity#onCreate super.onCreate()}.
*/
void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState);
/**
* Called as the last step of the Activity being created. This is always called after
* {@link Activity#onCreate}.
*/
default void onActivityPostCreated(@NonNull Activity activity,
@Nullable Bundle savedInstanceState) {
}
/**
* Called as the first step of the Activity being started. This is always called before
* {@link Activity#onStart}.
*/
default void onActivityPreStarted(@NonNull Activity activity) {
}
/**
* Called when the Activity calls {@link Activity#onStart super.onStart()}.
*/
void onActivityStarted(@NonNull Activity activity);
/**
* Called as the last step of the Activity being started. This is always called after
* {@link Activity#onStart}.
*/
default void onActivityPostStarted(@NonNull Activity activity) {
}
/**
* Called as the first step of the Activity being resumed. This is always called before
* {@link Activity#onResume}.
*/
default void onActivityPreResumed(@NonNull Activity activity) {
}
/**
* Called when the Activity calls {@link Activity#onResume super.onResume()}.
*/
void onActivityResumed(@NonNull Activity activity);
/**
* Called as the last step of the Activity being resumed. This is always called after
* {@link Activity#onResume} and {@link Activity#onPostResume}.
*/
default void onActivityPostResumed(@NonNull Activity activity) {
}
/**
* Called as the first step of the Activity being paused. This is always called before
* {@link Activity#onPause}.
*/
default void onActivityPrePaused(@NonNull Activity activity) {
}
/**
* Called when the Activity calls {@link Activity#onPause super.onPause()}.
*/
void onActivityPaused(@NonNull Activity activity);
/**
* Called as the last step of the Activity being paused. This is always called after
* {@link Activity#onPause}.
*/
default void onActivityPostPaused(@NonNull Activity activity) {
}
/**
* Called as the first step of the Activity being stopped. This is always called before
* {@link Activity#onStop}.
*/
default void onActivityPreStopped(@NonNull Activity activity) {
}
/**
* Called when the Activity calls {@link Activity#onStop super.onStop()}.
*/
void onActivityStopped(@NonNull Activity activity);
/**
* Called as the last step of the Activity being stopped. This is always called after
* {@link Activity#onStop}.
*/
default void onActivityPostStopped(@NonNull Activity activity) {
}
/**
* Called as the first step of the Activity saving its instance state. This is always
* called before {@link Activity#onSaveInstanceState}.
*/
default void onActivityPreSaveInstanceState(@NonNull Activity activity,
@NonNull Bundle outState) {
}
/**
* Called when the Activity calls
* {@link Activity#onSaveInstanceState super.onSaveInstanceState()}.
*/
void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState);
/**
* Called as the last step of the Activity saving its instance state. This is always
* called after{@link Activity#onSaveInstanceState}.
*/
default void onActivityPostSaveInstanceState(@NonNull Activity activity,
@NonNull Bundle outState) {
}
/**
* Called as the first step of the Activity being destroyed. This is always called before
* {@link Activity#onDestroy}.
*/
default void onActivityPreDestroyed(@NonNull Activity activity) {
}
/**
* Called when the Activity calls {@link Activity#onDestroy super.onDestroy()}.
*/
void onActivityDestroyed(@NonNull Activity activity);
/**
* Called as the last step of the Activity being destroyed. This is always called after
* {@link Activity#onDestroy}.
*/
default void onActivityPostDestroyed(@NonNull Activity activity) {
}
/**
* Called when the Activity configuration was changed.
* @hide
*/
default void onActivityConfigurationChanged(@NonNull Activity activity) {
}
}
通过上述接口,我们可以在合适的生命周期回调中获取 Activity
的 Bundle
参数。由于 Bundle
内部维护了一个 mMap
参数,因此可以通过遍历的方式获取所有的 key
,并根据 key 获取对应的 value 进行打印。
import android.app.Activity
import android.app.Application
import android.content.Intent
import android.os.Bundle
import com.blankj.utilcode.util.LogUtils
import org.json.JSONException
import org.json.JSONObject
class ActivityLifecycleLogger : Application.ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
LogUtils.d("onActivityCreated:===> exe...", activity, convertToJson(activity.intent))
}
private fun convertToJson(intent: Intent): String {
return intent.extras?.let { convertToJson(it) } ?: JSONObject().toString()
}
private fun convertToJson(bundle: Bundle): String {
val jsonObject = JSONObject()
for (key in bundle.keySet()) {
try {
jsonObject.put(key, bundle[key])
} catch (e: JSONException) {
e.printStackTrace()
}
}
return jsonObject.toString()
}
override fun onActivityStarted(activity: Activity) {
}
override fun onActivityResumed(activity: Activity) {
}
override fun onActivityPaused(activity: Activity) {
}
override fun onActivityStopped(activity: Activity) {
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
}
override fun onActivityDestroyed(activity: Activity) {
}
companion object {
@JvmStatic
val instance: Application.ActivityLifecycleCallbacks by lazy { ActivityLifecycleLogger() }
}
}
至此,我们已经实现了 Activity
跳转时参数的打印功能。但是,在实际开发中,Activity
内部可能会包含 Fragment
,而 Fragment
又可能存在嵌套情况,我们同样需要了解 Fragment
的创建过程以及传递给 Fragment
的参数。这时,系统提供的 FragmentLifecycleCallbacks
抽象类就派上了用场,我们可以通过 fragmentActivity.supportFragmentManager.registerFragmentLifecycleCallbacks()
方法注册 Fragment
的生命周期回调。
以下是
FragmentLifecycleCallbacks
抽象类的定义
/**
* Callback interface for listening to fragment state changes that happen
* within a given FragmentManager.
*/
@SuppressWarnings("unused")
public abstract static class FragmentLifecycleCallbacks {
/**
* Called right before the fragment's {@link Fragment#onAttach(Context)} method is called.
* This is a good time to inject any required dependencies or perform other configuration
* for the fragment before any of the fragment's lifecycle methods are invoked.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
* @param context Context that the Fragment is being attached to
*/
public void onFragmentPreAttached(@NonNull FragmentManager fm, @NonNull Fragment f,
@NonNull Context context) {}
/**
* Called after the fragment has been attached to its host. Its host will have had
* <code>onAttachFragment</code> called before this call happens.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
* @param context Context that the Fragment was attached to
*/
public void onFragmentAttached(@NonNull FragmentManager fm, @NonNull Fragment f,
@NonNull Context context) {}
/**
* Called right before the fragment's {@link Fragment#onCreate(Bundle)} method is called.
* This is a good time to inject any required dependencies or perform other configuration
* for the fragment.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
* @param savedInstanceState Saved instance bundle from a previous instance
*/
public void onFragmentPreCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
@Nullable Bundle savedInstanceState) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
* {@link Fragment#onCreate(Bundle)}. This will only happen once for any given
* fragment instance, though the fragment may be attached and detached multiple times.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
* @param savedInstanceState Saved instance bundle from a previous instance
*/
public void onFragmentCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
@Nullable Bundle savedInstanceState) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
* {@link Fragment#onActivityCreated(Bundle)}. This will only happen once for any given
* fragment instance, though the fragment may be attached and detached multiple times.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
* @param savedInstanceState Saved instance bundle from a previous instance
*
* @deprecated To get a callback specifically when a Fragment activity's
* {@link android.app.Activity#onCreate(Bundle)} is called, register a
* {@link androidx.lifecycle.LifecycleObserver} on the Activity's {@link Lifecycle} in
* {@link #onFragmentAttached(FragmentManager, Fragment, Context)}, removing it when it
* receives the {@link Lifecycle.State#CREATED} callback.
*/
@Deprecated
public void onFragmentActivityCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
@Nullable Bundle savedInstanceState) {}
/**
* Called after the fragment has returned a non-null view from the FragmentManager's
* request to {@link Fragment#onCreateView(LayoutInflater, ViewGroup, Bundle)}.
*
* @param fm Host FragmentManager
* @param f Fragment that created and owns the view
* @param v View returned by the fragment
* @param savedInstanceState Saved instance bundle from a previous instance
*/
public void onFragmentViewCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
@NonNull View v, @Nullable Bundle savedInstanceState) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
* {@link Fragment#onStart()}.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
public void onFragmentStarted(@NonNull FragmentManager fm, @NonNull Fragment f) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
* {@link Fragment#onResume()}.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
public void onFragmentResumed(@NonNull FragmentManager fm, @NonNull Fragment f) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
* {@link Fragment#onPause()}.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
public void onFragmentPaused(@NonNull FragmentManager fm, @NonNull Fragment f) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
* {@link Fragment#onStop()}.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
public void onFragmentStopped(@NonNull FragmentManager fm, @NonNull Fragment f) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
* {@link Fragment#onSaveInstanceState(Bundle)}.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
* @param outState Saved state bundle for the fragment
*/
public void onFragmentSaveInstanceState(@NonNull FragmentManager fm, @NonNull Fragment f,
@NonNull Bundle outState) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
* {@link Fragment#onDestroyView()}.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
public void onFragmentViewDestroyed(@NonNull FragmentManager fm, @NonNull Fragment f) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
* {@link Fragment#onDestroy()}.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
public void onFragmentDestroyed(@NonNull FragmentManager fm, @NonNull Fragment f) {}
/**
* Called after the fragment has returned from the FragmentManager's call to
* {@link Fragment#onDetach()}.
*
* @param fm Host FragmentManager
* @param f Fragment changing state
*/
public void onFragmentDetached(@NonNull FragmentManager fm, @NonNull Fragment f) {}
}
参照 Activity
参数打印的实现方式,我们可以编写如下代码来处理 Fragment
的参数打印。
activity.supportFragmentManager.registerFragmentLifecycleCallbacks(object :FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentCreated(fm: FragmentManager, f: Fragment, savedInstanceState: Bundle?) {
LogUtils.d("onFragmentCreated:===> exe...", f, savedInstanceState?.let { convertToJson(it) })
}
override fun onFragmentResumed(fm: FragmentManager, f: Fragment) {
LogUtils.d("onFragmentResumed:===> exe...", f)
}
}, true)
完整代码
import android.app.Activity
import android.app.Application
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import com.blankj.utilcode.util.LogUtils
import org.json.JSONException
import org.json.JSONObject
class ActivityLifecycleLogger : Application.ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
LogUtils.d("onActivityCreated:===> exe...", activity, convertToJson(activity.intent))
if (activity is FragmentActivity) {
activity.supportFragmentManager.registerFragmentLifecycleCallbacks(object :FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentCreated(fm: FragmentManager, f: Fragment, savedInstanceState: Bundle?) {
LogUtils.d("onFragmentCreated:===> exe...", f, savedInstanceState?.let { convertToJson(it) })
}
override fun onFragmentResumed(fm: FragmentManager, f: Fragment) {
LogUtils.d("onFragmentResumed:===> exe...", f)
}
}, true)
}
}
private fun convertToJson(intent: Intent): String {
return intent.extras?.let { convertToJson(it) } ?: JSONObject().toString()
}
private fun convertToJson(bundle: Bundle): String {
val jsonObject = JSONObject()
for (key in bundle.keySet()) {
try {
jsonObject.put(key, bundle[key])
} catch (e: JSONException) {
e.printStackTrace()
}
}
return jsonObject.toString()
}
override fun onActivityStarted(activity: Activity) {
}
override fun onActivityResumed(activity: Activity) {
}
override fun onActivityPaused(activity: Activity) {
}
override fun onActivityStopped(activity: Activity) {
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
}
override fun onActivityDestroyed(activity: Activity) {
}
companion object {
@JvmStatic
val instance: Application.ActivityLifecycleCallbacks by lazy { ActivityLifecycleLogger() }
}
}
食用方式
application.registerActivityLifecycleCallbacks(ActivityLifecycleLogger.getInstance())
结语
好啦,就写到这里吧 ,如果你想看更多的项目代码,请查看我在 Github 上的 阳光沙滩APP项目 ,你也可以在这里点击下载我写的 阳光沙滩APP客户端 进行体验。
如果对你有帮助的话,欢迎一键三连+关注哦~