使用Timber 和种植Timber trees 的最佳实践
日志是我们在开发安卓应用时的基本工作之一。然而,作为开发者,我们有时会使用传统的日志类。这些往往是很麻烦的。
Timber是一个由Jake Wharton 创建的库,它使日志记录变得毫不费力。
本文将讨论使用Timber 和种植Timber trees 的最佳实践。
要求
要舒适地跟上这个教程,你应该。
- 有一个可用的android studio IDE。
- 能够在
Android Studio中创建一个项目。 - 对
Kotlin或Java有所了解。 - 有一些关于
Logging class的基本知识。
目标
在本教程结束时,你应该能够。
- 知道什么是
Timber。 - 使用
Timber进行Android日志记录。
简介
在开发安卓应用程序时,日志记录是必不可少的,而且非常重要。我们几乎所有的事情都会用到日志。
例如,在调试if-else条件和处理异常时。然而,作为开发者,我们有时会使用传统的日志类。这些类往往很麻烦,而且很耗时。
Timber让日志记录变得容易实现,而且代码更少。
什么是 Logcat?
从官方文档来看,Android Studio中的logcat窗口显示系统信息。
例如,当发生垃圾收集时,logcat会实时显示这些消息。它也允许你查看较早的消息。
当你的代码抛出一个异常时,logcat会显示一个消息。异常包含一个相关的堆栈跟踪,包含与该行代码的链接。
传统的日志类消息有哪些?
根据官方文档,这个类允许创建日志消息。这些消息出现在logcat中。从最高的优先级到最低的(或者,从最不啰嗦到最啰嗦)。我们应该使用以下内容。
Log.e(String, String)- 显示错误Log.w(String, String)- 显示警告Log.i(String, String)-显示信息Log.d(String, String)-displays debug informationLog.v(String, String)- 为verbose
什么是Timber?
用传统的类进行日志记录是很麻烦的,这就是Timber 的作用。
在官方文档中,Timber 是一个具有小型、可扩展API的记录器。它在android的标准Log类的基础上提供了实用性。
Timber 也有几个日志信息。
Timber.i- 用于信息Timber.d- 调试信息Timber.v- 冗长的Timber.w和 - 用于警告Timber.wtf
它是如何工作的。
- 你通过在你的应用类中调用
Timber.plant,在你的onCreate,种植一棵树。 - 从任何类中调用
Timber。我们的类名就是我们可以用来作为标签的东西。
现在,我们来做一些编码吧...
在这个例子中,我们将创建一个应用程序,将两个数字相加。然后我们将记录答案。
第1步:创建项目
我们将通过创建一个项目来开始。下面的图片将指导你创建一个项目。

第2步:添加木材依赖性
创建项目后,我们将把Timber's 依赖关系添加到我们的应用级构建 Gradle 中。
//Timber dependency
implementation 'com.jakewharton.timber:timber:4.7.1'

第3步:XML布局
我们现在将创建和设计我们的布局。
主要活动布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/first_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Enter Number..."
android:inputType="number"
android:textColor="#000000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.19999999" />
<EditText
android:id="@+id/second_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Enter Number..."
android:inputType="number"
android:textColor="#000000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/first_number"
app:layout_constraintVertical_bias="0.120000005" />
<TextView
android:id="@+id/answer"
android:layout_width="0dp"
android:layout_height="40dp"
android:gravity="center"
android:textColor="#000000"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/second_number" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#F4511E"
android:text="Add"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/answer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/second_number" />
</androidx.constraintlayout.widget.ConstraintLayout>
第4步:Timber应用类
创建布局后,我们将为我们的Application class of Timber 编写代码
import android.app.Application;
import timber.log.Timber;
public class TimberDemoApp extends Application {
@Override
public void onCreate() {
super.onCreate();
Timber.plant(new Timber.DebugTree());
}
}

import android.app.Application
import timber.log.Timber
import timber.log.Timber.DebugTree
class TimberDemoApp : Application() {
override fun onCreate() {
super.onCreate()
Timber.plant(DebugTree())
}
}
创建类后,用名称标签更新你的Manifest file 。使用你的应用类作为值,如下图所示。
第5步:代码。(主要活动)
在这一步中,我们将为上面设计的两个数字梯子编写代码。
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import timber.log.Timber;
public class MainActivity extends AppCompatActivity {
private Button button;
private EditText num1, num2;
private TextView answer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
num1 = findViewById(R.id.first_number);
num2 = findViewById(R.id.second_number);
answer = findViewById(R.id.answer);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int first_number = Integer.parseInt(num1.getText().toString().trim());
int second_number = Integer.parseInt(num2.getText().toString().trim());
if (num1.getText().toString().isEmpty() || num2.getText().toString().isEmpty()){
num1.setError("Cannot be empty!!");
}
else{
int sum = first_number+second_number;
answer.setText(String.valueOf(sum));
Timber.v(answer.getText().toString());
}
}
});
}
}
Kotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import timber.log.Timber
class MainActivity : AppCompatActivity() {
private lateinit var button:Button
private lateinit var num1:EditText
private lateinit var num2:EditText
private lateinit var answer:TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button = findViewById(R.id.button)
num1 = findViewById(R.id.first_number)
num2 = findViewById(R.id.second_number)
answer = findViewById(R.id.answer)
button.setOnClickListener {
val first_number = num1.text.toString().trim { it <= ' ' }.toInt()
val second_number = num2.text.toString().trim { it <= ' ' }.toInt()
if (num1.text.toString().isEmpty() || num2.text.toString().isEmpty()) {
num1.error = "Cannot be empty!!"
} else {
val sum = first_number + second_number
answer.text = sum.toString()
Timber.d(answer.text.toString())
}
}
}
}
木材Logcat
在logcat中,你会看到这样一行字:D/MainActivity: 我们没有指定类名,但Timber为我们放置了一个。这就是Timber 的妙处。
示范屏幕
让我们在一个设备或模拟器上运行该应用程序。logcat的输出应该如下图所示。


结论
这不是关于Logging with Timber 的全部;继续探索。
在你的android应用中使用这个神奇的工具实现日志记录,并提高你的应用日志的可读性。