Home > Software engineering >  Why Timber log produces the log messages twice once the activity restart its lifecycle in Android?
Why Timber log produces the log messages twice once the activity restart its lifecycle in Android?

Time:11-05

During the development of my Android project, I encountered the encouraged use of the Timber log library; but when I switched to using it, I found that once the activity in which I place Timber.plant(new Timber.DebugTree()); restarts its lifecycle (calling onCreate(savedInstanceState) a second time), all the log generated by Timber get produced twice in the LogCat panel.

This simple code illustrates the problem:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "StateChange";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        Timber.plant(new Timber.DebugTree());   // plant a debug tree
        
        setContentView(ActivityMainBinding.inflate(getLayoutInflater()).getRoot());

        Timber.tag(TAG).i("onCreate");  // using timber log
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy");    // using android log
    }
}

Now when I run the app and rotate the screen (which will cause the activity to destroy and recreate again), the content of the LogCat is as follow:

... I/StateChange: onCreate     <-- everything is normal in the first creation
... I/StateChange: onDestroy    
... I/StateChange: onCreate     <-- when lifecycle restarts (rotate screen)
... I/StateChange: onCreate     <-- those use Timber will get logged twice
... I/StateChange: onDestroy    <-- but those use standard log remain normal
... I/StateChange: onCreate     <-- rotate again
... I/StateChange: onCreate     <-- same problem, but only twice

So anyway this is still my first use of Timber, I don't know if we should put any code anywhere to handle the situation. Although this seems harmless enough, the project I am currently doing involves a lot of debugging from the LogCat panel, and looking at twice as much information to debug the app is really cumbersome.

CodePudding user response:

This is the expected behaviour. After all, you are planting a new "Debug tree" every time the activity gets created.

Instead of doing it this way, you should have a Custom Application class and override the onCreate function. Inside, just plant the "Debug tree".

E.g.:

public class MyCustomApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        Timber.plant(new Timber.DebugTree());
        ...
}

This way, the Timber debug tree will only be "planted" on app initialisation.

CodePudding user response:

You should plant your Timber on your Application onCreate() method, not on Activity onCreate() method. Otherwise you can wrap your Timber.plant() method into condition like this:

if (Timber.treeCount() == 0) {
    Timber.plant(new Timber.DebugTree());   // plant a debug tree
}
  • Related