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
}