Android Activity生命周期重启时Timber日志重复打印的原因及解决方法
问题成因
Timber的日志树存储在全局静态集合中,每次调用Timber.plant()方法都会向该集合新增一个日志树实例。每次打印日志时,Timber会遍历所有已种植的日志树,依次执行日志输出逻辑。
你将Timber.plant(new Timber.DebugTree())写在Activity的onCreate方法中,每次Activity因配置变更(如屏幕旋转)重建时,都会重复种植新的DebugTree实例,N次重建就会有N个日志树,最终同一条日志会被输出N次,你遇到的二次输出就是因为已经种植了2个DebugTree。
解决方法
推荐方案:全局初始化Timber
Timber官方推荐将初始化逻辑放在Application的onCreate方法中,Application全局仅会初始化一次,不会出现重复种植日志树的问题。
- 自定义Application类:
public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); // 建议仅在Debug版本初始化DebugTree,避免线上环境输出敏感日志 if (BuildConfig.DEBUG) { Timber.plant(new Timber.DebugTree()); } } }
- 在
AndroidManifest.xml的application节点中注册自定义Application:
<application android:name=".MyApp" ...其余配置保持不变...> ...Activity等组件声明... </application>
- 删除Activity中
onCreate方法内的Timber.plant(new Timber.DebugTree())代码即可。
特殊场景方案:需在Activity中初始化
如果确实有业务需求需要在Activity内初始化Timber,可以选择以下两种方式避免重复种植:
方式1:静态标记判断是否已初始化
public class MainActivity extends AppCompatActivity { private static final String TAG = "StateChange"; // 静态标记全局仅会初始化一次,不受Activity重建影响 private static boolean sTimberInitialized = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (!sTimberInitialized) { Timber.plant(new Timber.DebugTree()); sTimberInitialized = true; } setContentView(ActivityMainBinding.inflate(getLayoutInflater()).getRoot()); Timber.tag(TAG).i("onCreate"); } @Override protected void onDestroy() { super.onDestroy(); Log.i(TAG, "onDestroy"); } }
方式2:Activity销毁时移除对应日志树
public class MainActivity extends AppCompatActivity { private static final String TAG = "StateChange"; private Timber.Tree mDebugTree; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDebugTree = new Timber.DebugTree(); Timber.plant(mDebugTree); setContentView(ActivityMainBinding.inflate(getLayoutInflater()).getRoot()); Timber.tag(TAG).i("onCreate"); } @Override protected void onDestroy() { super.onDestroy(); // 移除当前Activity种植的日志树,避免后续重复 Timber.uproot(mDebugTree); Log.i(TAG, "onDestroy"); } }
内容的提问来源于stack exchange,提问作者hescul
相关产品推荐
相关产品推荐

