您的位置:首页 > 其它

Log.isLoggable之一正确的使用姿势

2017-06-05 15:27 447 查看
相关文章

Log.isLoggable之一正确的使用姿势

Log.isLoggable之二源码解析

简介

我们在做Android APP开发时,多多少少需要打印Log,伴随着Log的打印就有一个打印开关是否允许打印Log,本文要讲的就是这个打印开关Log.isLoggable的使用和源码解析。

DEBUG方法比较

当我们在做APP开发时,需要设置调试开关打印Log,下面我列举出3种方法:

方法一:直接赋值

public static final boolean DEBUG = true;//false


方法二:设置BuildConfig.DEBUG的值

public static final boolean DEBUG = BuildConfig.DEBUG;


方法三:设置Log.isLoggable的值

public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);


当然这里可能还有很多别的设置方法,由于个人局限就没有写了。下面我们来看看上面3种方法各自的特点:

方法一比较直观明了,可以清楚的知道是否允许打印Log。

方法二和编译模式绑定,如果是release版的就不会打印Log,如果是debug版的话就会打印Log。

方法三通过设置property属性来打印Log

从他们的特点来看我们知道,第一种和第二种方法我们至少需要编译两个版本的软件用于发布和调试。

第三种方法我们只需要编译一个版本既可以。在我们需要查看Log的时候,通过设置property即可查看Log。下面来详细介绍下Log.isLoggable的使用。

Log.isLoggable的使用姿势

步骤一:

MainActivity.java

public static final String TAG = "Main";
public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

public void onCreate(){
if (DEBUG){
Log.d(TAG, "onCreate");
}
}


步骤二:

adb shell setprop log.tag.Main D


或者

修改/data/local.prop文件(该方法不一定有效,根据不同的系统,可能不会去读取local.prop文件)

log.tag.Main=D


注:这里的TAG要加上log.tag.做前缀

步骤三:

退出APP,重新进入,即可打印Log(注:这里之所以要退出APP是因为我们定义的DEBUG是全局的,所以需要重新赋值)。

当然你们也可以设置成局部变量,这样就不需要重新进入了,这样就可以免除第三步。

Log.isLoggable实战

public class MainActivity extends Activity implements OnClickListener {

//各个Log级别定义的值,级别越高值越大
/*
public static final int VERBOSE = 2;
public static final int DEBUG = 3;
public static final int INFO = 4;
public static final int WARN = 5;
public static final int ERROR = 6;
public static final int ASSERT = 7;
*/

private static final String TAG = "Hello";
//定义全局的Log开关
private boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
private boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private boolean INFO = Log.isLoggable(TAG, Log.INFO);
private boolean WARN = Log.isLoggable(TAG, Log.WARN);
private boolean ERROR = Log.isLoggable(TAG, Log.ERROR);
private boolean ASSERT = Log.isLoggable(TAG, Log.ASSERT);
private boolean SUPPRESS = Log.isLoggable(TAG, -1);

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

findViewById(R.id.id_verbose).setOnClickListener(this);
}

/**
* 更新loggable值
*/
private void update() {
//局部的Log开关
VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
DEBUG = Log.isLoggable(TAG, Log.DEBUG);
INFO = Log.isLoggable(TAG, Log.INFO);
WARN = Log.isLoggable(TAG, Log.WARN);
ERROR = Log.isLoggable(TAG, Log.ERROR);
ASSERT = Log.isLoggable(TAG, Log.ASSERT);
SUPPRESS = Log.isLoggable(TAG, -1);
}

@Override
public void onClick(View v) {
update();

switch (v.getId()) {
case R.id.id_verbose:
Log.d(TAG, "------------------start------------------------");
if (VERBOSE) {
Log.d(TAG, "verbose log");
}
if (DEBUG) {
Log.d(TAG, "debug log");
}
if (INFO) {
Log.d(TAG, "info log");
}
if (WARN) {
Log.d(TAG, "warn log");
}
if (ERROR) {
Log.d(TAG, "error log");
}
if (ASSERT) {
Log.d(TAG, "assert log");
}
if (SUPPRESS) {
Log.d(TAG, "suppress log");
}
Log.d(TAG, "------------------end------------------------");
break;

default:
break;
}
}
}


上面的代码我们已经将所有的Log开关都定义了,并设置了相应的打印信息。下面我们来看下其相关的打印日志。

1.没有做任何操作时的Log

06-05 13:37:06.436: D/Hello(2651): ------------------start------------------------
06-05 13:37:06.436: D/Hello(2651): info log
06-05 13:37:06.436: D/Hello(2651): warn log
06-05 13:37:06.436: D/Hello(2651): error log
06-05 13:37:06.436: D/Hello(2651): assert log
06-05 13:37:06.436: D/Hello(2651): ------------------end------------------------


2.设置adb shell setprop log.tag.Hello V

06-05 13:38:49.102: D/Hello(2651): ------------------start------------------------
06-05 13:38:49.102: D/Hello(2651): verbose log
06-05 13:38:49.102: D/Hello(2651): debug log
06-05 13:38:49.102: D/Hello(2651): info log
06-05 13:38:49.102: D/Hello(2651): warn log
06-05 13:38:49.102: D/Hello(2651): error log
06-05 13:38:49.102: D/Hello(2651): assert log
06-05 13:38:49.103: D/Hello(2651): ------------------end------------------------


3.设置adb shell setprop log.tag.Hello D

06-05 13:39:42.593: D/Hello(2651): ------------------start------------------------
06-05 13:39:42.593: D/Hello(2651): debug log
06-05 13:39:42.593: D/Hello(2651): info log
06-05 13:39:42.593: D/Hello(2651): warn log
06-05 13:39:42.593: D/Hello(2651): error log
06-05 13:39:42.593: D/Hello(2651): assert log
06-05 13:39:42.593: D/Hello(2651): ------------------end------------------------


4.设置adb shell setprop log.tag.Hello I

06-05 13:40:21.949: D/Hello(2651): ------------------start------------------------
06-05 13:40:21.949: D/Hello(2651): info log
06-05 13:40:21.949: D/Hello(2651): warn log
06-05 13:40:21.949: D/Hello(2651): error log
06-05 13:40:21.949: D/Hello(2651): assert log
06-05 13:40:21.949: D/Hello(2651): ------------------end------------------------


5.设置adb shell setprop log.tag.Hello W

06-05 13:41:26.370: D/Hello(2651): ------------------start------------------------
06-05 13:41:26.370: D/Hello(2651): warn log
06-05 13:41:26.370: D/Hello(2651): error log
06-05 13:41:26.370: D/Hello(2651): assert log
06-05 13:41:26.370: D/Hello(2651): ------------------end------------------------


6.设置adb shell setprop log.tag.Hello E

06-05 13:41:58.954: D/Hello(2651): ------------------start------------------------
06-05 13:41:58.954: D/Hello(2651): error log
06-05 13:41:58.954: D/Hello(2651): assert log
06-05 13:41:58.954: D/Hello(2651): ------------------end------------------------


7.设置adb shell setprop log.tag.Hello A

06-05 13:42:56.747: D/Hello(2651): ------------------start------------------------
06-05 13:42:56.748: D/Hello(2651): assert log
06-05 13:42:56.748: D/Hello(2651): ------------------end------------------------


8.设置adb shell setprop log.tag.Hello S

06-05 13:43:46.563: D/Hello(2651): ------------------start------------------------
06-05 13:43:46.563: D/Hello(2651): ------------------end------------------------


通过上面的Log信息可以分析到,我们通过adb shell setprop设置相应的级别和代码中Log.isLoggable设置的级别比较,当Log.isLoggable设置的级别大于或等于setprop设置的级别时,Log开关即打开,就可以打印Log了。同时,我们设置的S级别的Log,怎么样都不会打印Log。我们没有setprop任何Log级别时,默认打印的是设置Info级别的Log,从这里我们也可以知道,在实际代码Log开关定义中,最好设置成DEBUG级别,这样就可以通过setprop来设置是否需要打印Log。

frameworks中的模块使用Log.isLoggable

当APP使用Log.isLoggable并定义为全局变量时,我们可以setprop后重启app打印相关的Log。那frameworks中如果有Log.isLoggable要怎么打印呢?只需要执行下面3步即可:

adb shell setprop log.tag.<TAG> D
adb shell stop
adb shell start


adb shell stop会杀掉zygote进程以及所有由zygote孵化而来的子进程。adb shell start则会重启zygote进程,再由zygote进程启动其它Android核心进程。当zygote重新启动时,会重新加载framework相关资源,而此时属性已经设置。

总结

通过上面的实战分析,我们在做Log开关的时候,采用Log.isLoggable的方式,最好使用DEBUG级别这样我们就可以控制Log的打印了。同时,需要注意的是setprop设置Log级别的方法是一次性的,即如果机器重启后,就不会生效了。如果要想永久生效,就可以把属性值写入prop文件中,本文就不细讲了。下文Log.isLoggable之二源码解析讲源码解析时在介绍有哪些prop文件可以写入其属性。

源码

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: