使用Log的一些姿势

LOG 是任何一种编程语言的第一个API,通常被初学者用来打印 Hello, World!。 有研究显示,

不使用 LOG 或者使用姿势错误的人,感情路都走得很辛苦,有七成的比例会在 34 岁的时候跟自己不爱的人结婚,而其余三成的人最后只能把遗产留给自己的猫。毕竟爱情需要书写,不能是一整张白纸。

LogCat是Android开发者们最熟悉不过的日志打印工具,几乎每一个Android项目里面都包含着大量的Log相关代码。不过,或许是因为Log实在是太过于普通,所以许多人在使用它的时候就显得非常随意,这些错误的使用姿势却会在不经意间给我们带来不少的大坑。

Log相关的一些问题

没有关闭调试用的LOG

许多同学喜欢在开发阶段用Log输出当前的一些环境数据,用于调试代码,但是在调试完成后却忘了关闭这些Log,导致发版出去的应用里面还会继续输出这些LOG,这样不仅会造成不必要的性能丢失,也会暴露一些敏感的数据,这些都是我们不愿看到的。

首先,我们要给Log进行分级,规定“DEBUG版本输出哪一些级别的LOG并屏蔽哪一些级别的LOG,而RELEASE版本又输出另一些级别的LOG并屏蔽另一些级别的LOG”,这样在开发阶段能够输出我们调试需要的LOG,而同时又能保证放送的版本能够屏蔽这些敏感的LOG。但是在开发阶段我们不应该特意去注意这些细节,所以必须开发一个Log工具库,在框架层级解决这个需求。

同时,需要注意的是,用于作为“开启/关闭Log”的开关必须是一个常量,而不能是一个变量(使用常量的话,在编译代码的时候,如果常量为false),编译器会直接把调试部分的Log代码直接去掉,而使用变量作为开关的话,这个判断逻辑会继续保留,一方面会造成性能丢失,另一方面在运行时也可以通过Hack手段强行开启这部分Log代码。

另外,“开启/关闭Log”的开关必须写在Log方法外部,也就是说必须先判断“开启/关闭Log”条件,再调用Log方法,因为在调用Log方法的时候已经造成了性能丢失,而且调用方法的时候,会先构造好改方法需要的参数(按照参数顺序从右往左),再调用方法,而许多人喜欢在调用Log方法的时候计算需要打印出来的内容,这里是最容易造成性能丢失的地方。因此,如果为了图方便,写一个Log工具类,在工具类内部去判断是否应该开启或关闭Log,事实上已经造成了不少的性能丢失。正确的使用姿势应该是:


  1. public static final boolean DEBUG = true; 
  2.  
  3. if (DEBUG) { 
  4.   Log.v(TAG, "log something"); 
  5. }  

在循环体内部打印LOG

尽管Log造成的性能损失很小,但是如果在循环体内部循环调用Log方法的话,那总体的丢失的非常可观了,所以不应该在循环体内部使用Log,正确的做法是在循环体内部拼接需要打印的内容,等跳出循环体再一次打印出来。

除了常见的循环体外,还要一个需要注意的场景就是Adapter。ListView/RecyclerView是Android开发中最常用的控件,因此Adapter使用的情景也很多。滚动屏幕的时候,ListView/RecyclerView会在通过Adapter频繁地绑定ItemView和数据,而且这些都是在UI线程里进行的,所以如果在绑定的过程中调用Log,可能会造成明显的卡顿。

至于Log到底会丢失多少性能,一般情况下,Log的性能丢失很小,毕竟是这么常见的系统Api,肯定是身经百战,早就是“best performance”了。不过我曾经有个RecyclerView在MIUI上非常卡,一开始我是RecyclerView布局没优化好,最终定位到Adapter内部的一处Log上,卡顿的地方出现在Log的Native实现。MIUI到底对用户输出的日志做了什么处理呢?非常神奇。

无法获取重要LOG内容

在调试代码的时候,我们经常通过LOG来定位Bug。同理,当线上的版本出现问题的时候,我们也希望能通过LOG来定位问题所在。但是问题是用户的设备上的打印出来的LOG我们根本没有方法获取,唯一的手段就是当用户设备出现问题的时候,把设备借过来连上IDE用LogCat查看输出的LOG……显然这是不可行的。

这种时候,我们可以在打印重要LOG(比如重要路径的触发点、或者一些异常类的信息)的时候,一并把这些信息记录到文件里。在用户反馈系统里面,一并将这些文件上传到我们的用户反馈服务器,这样在处理反馈问题的时候,就能拿到重要的参考日志了。

BLog

BLog 是 Android SDK 的 LOG 工具 {@Link android.util.Log} 的加强版,以方便在开发时用来

操作调试日志。

特点

  1. 简单易用的API;
  2. 支持输出线程信息;
  3. 支持设置LogLevel,方便在生产环境关闭调试用的LOG;
  4. 支持将LOG内容写入文件,以便通过文件LOG定位用户反馈的问题;

注意,尽管BLog支持关闭Log的输出,但是在你调用 BLog.v(String) 的时候,其实已经造成了性能

丢失,所以请尽量使用正确的姿势来使用BLog,比如


  1. if (BuildConfig.DEBUG) {   
  2. BLog.v(TAG, "log verbose"); 

作者:Kaede

来源:51CTO

时间: 2024-10-31 22:10:50

使用Log的一些姿势的相关文章

DockOne微信分享(一二八):容器化部署OpenStack的正确姿势

本文讲的是DockOne微信分享(一二八):容器化部署OpenStack的正确姿势[编者的话]当前,以OpenStack为代表的IaaS开源技术和以Docker为代表的PaaS/CaaS容器技术日益成熟,二者如何强强联合,一直是业界颇为关心的焦点领域.本次分享主要是和大家交流基于Docker容器运行和部署OpenStack.那么,安装OpenStack都有哪些方法呢?对于很多刚接触OpenStack的新人而言,安装无疑是一大挑战,同时也直接提高了学习OpenStack云计算的技术门槛. [3 天

awk-正则表达式匹配不成功,求解释原因及正确姿势

问题描述 正则表达式匹配不成功,求解释原因及正确姿势 日志部分内容如下: 2016-02-21 09:59:58.522 INFO 0a030860-2003-24266999-236 c3 /result/payNotifyResult.htm 17 0 2016-02-21 09:59:59.092 INFO 0a030860-2003-24266999-237 c0 /cashier/getCode.htm 1 71 2016-02-21 09:59:59.303 INFO 0a03086

Day09 - Console 调试各种姿势指南

作者:liyuechun简介:JavaScript30 是 Wes Bos 推出的一个 30 天挑战.项目免费提供了 30 个视频教程.30 个挑战的起始文档和 30 个挑战解决方案源代码.目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用.现在你看到的是这系列指南的第 9 篇.完整中文版指南及视频教程在 从零到壹全栈部落. 项目效果 各种调试正确姿势 .log 的更多用法 这个是最常用的,但它还有一些更多功能:比如参数支持类似 C 语言的字符串替换模式.

以什么姿势进入DataMining会少走弯路?

前言:大数据时代早已经来临,很多年轻人急着闹着想要跻身于大数据行业,不免也有一些不得志的中年人.自然而然的会报各种培训班,理所当然认为付出总有一天会赚回来的.但却走了不少弯路,花了不少钱.倘若在我写的文章中,能有所启发和收获,希望诸位能够以恰当的姿势进入DataMining吧! 画外音:看过身边花1w+大洋报培训班,周末夜里坚持学习的同学;面过硕士.博士甚至留学交换生,但结果总不尽如人意;现如今堪比前端一样浑浊的算法领域,让人担忧. 承认一点,每个人都在进步,每个人都走过弯路,曾几某时,自己也一

Android屏幕锁屏弹窗的正确姿势DEMO详解_Android

在上篇文章给大家介绍了Android程序开发仿新版QQ锁屏下弹窗功能.今天通过本文给大家分享android锁屏弹窗的正确姿势. 最近在做一个关于屏幕锁屏悬浮窗的功能,于是在网上搜索了很多安卓屏幕锁屏的相关资料,鉴于网上的资料比较零碎,所以我在这里进行整理总结.本文将从以下两点对屏幕锁屏进行解析: 1. 如何监听系统屏幕锁屏 2. 如何在锁屏界面弹出悬浮窗 如何监听系统屏幕锁屏 经过总结,监听系统的锁屏可以通过以下两种方式: 1) 代码直接判定 2) 接收广播 1) 代码直接判定 代码判断方式,也

JavaScript 姿势提升简略

本文讲的是JavaScript 姿势提升简略, JavaScript 是一门入门容易,但是相当难以精通的语言.可现今一些文章总假设你已经精通了它. 我从 1995 年 JavaScript 还以 LiveScript 名字出现的时候就开始用它了,但后来逐渐从前端开发撤回服务器的安全怀抱中,直到五年前才重拾.很高兴看到如今的浏览器更加的强大和易于调试.但 JavaScript 已经演变得越来越复杂且难以精通了.不过最近我终于得出结论,我并不需要_精通_ Javascript,只需要比以前更进一步就

探索 PHP project 或 package 的标准开发姿势

探索 PHP project 或 package 的合理开发姿势 合适的开发姿势对于开发优秀的项目或产品是很重要的,无奈本人经验有限,若有不同看法或者错误的表述,欢迎交流指正,以免无人子弟 ^ ^ 基于 PDS-Skeleton 创建一个新项目,并且安装 phpunit. git clone https://github.com/php-pds/skeleton blog cd blog composer require phpunit/phpunit --dev 进入项目目录后,可以看到当前的

Retrofit2.0通俗易懂的学习姿势,Retrofit2.0 + OkHttp3 + Gson + RxJava

Retrofit2.0通俗易懂的学习姿势,Retrofit2.0 + OkHttp3 + Gson + RxJava Retrofit,因为其简单与出色的性能,也是受到很多人的青睐,但是他和以往的通信框架还是有点区别,不过放心,因为他本身还是挺简单的,所有我相信你看完这篇文章,对基本的请求是没什么问题的,其实现在网上这样的文章也有很多了,好了,那我们直接开车吧! 一.相关资料 Github:https://github.com/square/retrofit 官网文档:http://square

SpriteBuilder添加的TrueType字体未显示在log中的原因分析

按照书上的说法,在SpriteBuilder中添加的TrueType字体名称会在枚举字体方法显示的log中出现.但是运行程序后没有在log中发现对应的字体名称. 因为该字体是例子中作者制作的,所以字体名称与文件名称一定是匹配的(除了没有文件后缀).而且在运行的程序中的确看到了该字体正确的显示效果(Settings用的是系统自带字体,Slider左边的label字体是用户的TrueType字体): 这就证明字体已经加载成功了,但是为毛log中没有呢? 后来才知道,原来log是在MainScene中