1. 简介
ToolargeTool 是一个 Android 库,用于检测 Bundle 或 Intent 传输的数据是否过大,以防止 TransactionTooLargeException。该异常通常发生在 Activity、Fragment 或 Service 之间传输大数据时,可能导致应用崩溃。ToolargeTool 提供了简便的方法来监控和调试此类问题。
2. 项目结构
ToolargeTool 的项目结构如下:
toolargetool/
│
├── src/main/java/com/gu/toolargetool/
│ ├── ToolargeTool.java
│ ├── ActivityLifecycleCallbacksImpl.java
│ ├── FragmentLifecycleCallbacksImpl.java
│ ├── LogProxy.java
│ └── Util.java
各个文件的功能如下:
ToolargeTool.java:库的主类,提供初始化和监控功能。ActivityLifecycleCallbacksImpl.java:用于监听 Activity 生命周期事件。FragmentLifecycleCallbacksImpl.java:用于监听 Fragment 生命周期事件。LogProxy.java:日志代理类,用于输出日志信息。Util.java:工具类,提供辅助功能。
3. 核心类分析
3.1 ToolargeTool 类
ToolargeTool 类是库的核心类,负责初始化和监控功能。
public final class ToolargeTool {
private static final String TAG = "ToolargeTool";
private ToolargeTool() {
}
public static void startLogging(Application application) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
registerActivityLifecycleCallbacks(application);
registerFragmentLifecycleCallbacks(application);
} else {
Log.w(TAG, "ToolargeTool requires Android O or higher");
}
}
private static void registerActivityLifecycleCallbacks(Application application) {
application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacksImpl());
}
private static void registerFragmentLifecycleCallbacks(Application application) {
FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks = new FragmentLifecycleCallbacksImpl();
for (Activity activity : application.getActivityLifecycleCallbacks()) {
if (activity instanceof FragmentActivity) {
((FragmentActivity) activity).getSupportFragmentManager()
.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true);
}
}
}
}
startLogging 方法是入口方法,用于初始化监控。它注册了 Activity 和 Fragment 的生命周期回调,以便在生命周期事件中检测数据大小。
3.2 ActivityLifecycleCallbacksImpl 类
ActivityLifecycleCallbacksImpl 类实现了 Application.ActivityLifecycleCallbacks 接口,用于监听 Activity 的生命周期事件。
public class ActivityLifecycleCallbacksImpl implements Application.ActivityLifecycleCallbacks {
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
if (outState != null) {
int size = Util.getBundleSize(outState);
if (size > Util.THRESHOLD) {
LogProxy.log(activity.getLocalClassName() + " onSaveInstanceState bundle size: " + size + " bytes");
}
}
}
// 其他生命周期方法省略
}
onActivitySaveInstanceState 方法在保存 Activity 状态时调用,通过 Util.getBundleSize 方法计算 Bundle 大小,并在超过阈值时输出日志。
3.3 FragmentLifecycleCallbacksImpl 类
FragmentLifecycleCallbacksImpl 类实现了 FragmentManager.FragmentLifecycleCallbacks 接口,用于监听 Fragment 的生命周期事件。
public class FragmentLifecycleCallbacksImpl extends FragmentManager.FragmentLifecycleCallbacks {
@Override
public void onFragmentSaveInstanceState(FragmentManager fm, Fragment f, Bundle outState) {
if (outState != null) {
int size = Util.getBundleSize(outState);
if (size > Util.THRESHOLD) {
LogProxy.log(f.getClass().getSimpleName() + " onSaveInstanceState bundle size: " + size + " bytes");
}
}
}
// 其他生命周期方法省略
}
onFragmentSaveInstanceState 方法在保存 Fragment 状态时调用,通过 Util.getBundleSize 方法计算 Bundle 大小,并在超过阈值时输出日志。
3.4 LogProxy 类
LogProxy 类用于输出日志信息,可以替换为自定义的日志处理逻辑。
public class LogProxy {
public static void log(String message) {
Log.d("ToolargeTool", message);
}
}
3.5 Util 类
Util 类提供辅助功能,如计算 Bundle 大小。
public class Util {
public static final int THRESHOLD = 512 * 1024; // 512KB
public static int getBundleSize(Bundle bundle) {
Parcel parcel = Parcel.obtain();
bundle.writeToParcel(parcel, 0);
int size = parcel.dataSize();
parcel.recycle();
return size;
}
}
getBundleSize 方法通过将 Bundle 写入 Parcel 并获取其数据大小来计算 Bundle 大小。
4. 具体实现分析
4.1 初始化监控
ToolargeTool 的初始化通过调用 startLogging 方法实现。该方法首先判断当前 Android 版本是否高于 O,然后注册 Activity 和 Fragment 的生命周期回调。
public static void startLogging(Application application) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
registerActivityLifecycleCallbacks(application);
registerFragmentLifecycleCallbacks(application);
} else {
Log.w(TAG, "ToolargeTool requires Android O or higher");
}
}
4.2 监听 Activity 和 Fragment 生命周期
在 registerActivityLifecycleCallbacks 和 registerFragmentLifecycleCallbacks 方法中,分别注册了 ActivityLifecycleCallbacksImpl 和 FragmentLifecycleCallbacksImpl。
private static void registerActivityLifecycleCallbacks(Application application) {
application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacksImpl());
}
private static void registerFragmentLifecycleCallbacks(Application application) {
FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks = new FragmentLifecycleCallbacksImpl();
for (Activity activity : application.getActivityLifecycleCallbacks()) {
if (activity instanceof FragmentActivity) {
((FragmentActivity) activity).getSupportFragmentManager()
.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true);
}
}
}
4.3 计算 Bundle 大小
在 ActivityLifecycleCallbacksImpl 和 FragmentLifecycleCallbacksImpl 中,分别在 onActivitySaveInstanceState 和 onFragmentSaveInstanceState 方法中计算 Bundle 大小。
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
if (outState != null) {
int size = Util.getBundleSize(outState);
if (size > Util.THRESHOLD) {
LogProxy.log(activity.getLocalClassName() + " onSaveInstanceState bundle size: " + size + " bytes");
}
}
}
@Override
public void onFragmentSaveInstanceState(FragmentManager fm, Fragment f, Bundle outState) {
if (outState != null) {
int size = Util.getBundleSize(outState);
if (size > Util.THRESHOLD) {
LogProxy.log(f.getClass().getSimpleName() + " onSaveInstanceState bundle size: " + size + " bytes");
}
}
}
通过 Util.getBundleSize 方法计算 Bundle 大小,并在超过阈值时输出日志。
5. 使用示例
在应用程序中使用 ToolargeTool 非常简单,只需在 Application 类中调用 ToolargeTool.startLogging 方法。
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
ToolargeTool.startLogging(this);
}
}
6. 总结
ToolargeTool 是一个轻量级的 Android 库,提供了简便的方法来监控 Bundle 或 Intent 数据的大小,防止 TransactionTooLargeException。通过对其源码的分析,我们可以看到它通过注册 Activity 和 Fragment 的生命周期回调,在数据保存时计算 Bundle 大小,并在超过阈值时输出日志,帮助开发者及时发现和解决问题。其实现简单高效,适合在项目中集成和使用。