1、背景
本日誌打印工具類支持超長文本信息打印,支持點擊日誌直接定位到對應代碼行。 我有借鑑com.orhanobut:logger這位兄弟的代碼。廢話不多說,直接上效果圖。
2、類源碼
public class HLogger {
public static boolean DEBUG = true;
private static final int CHUNK_SIZE = 100;
private static final char TOP_LEFT_CORNER = '┌';
private static final char BOTTOM_LEFT_CORNER = '└';
private static final char MIDDLE_CORNER = '├';
private static final char HORIZONTAL_LINE = '│';
private static final String DOUBLE_DIVIDER = "────────────────────────────────────────────────────────";
private static final String SINGLE_DIVIDER = "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄";
private static final String TOP_BORDER = TOP_LEFT_CORNER + DOUBLE_DIVIDER + DOUBLE_DIVIDER;
private static final String BOTTOM_BORDER = BOTTOM_LEFT_CORNER + DOUBLE_DIVIDER + DOUBLE_DIVIDER;
private static final String MIDDLE_BORDER = MIDDLE_CORNER + SINGLE_DIVIDER + SINGLE_DIVIDER;
private static String className;
private static String methodName;
private static int lineNumber;
private static String createLog(String log) {
StringBuffer buffer = new StringBuffer();
buffer.append(methodName);
buffer.append("(").append(className).append(":").append(lineNumber).append(")");
buffer.append(log);
return buffer.toString();
}
private static String createLog() {
StringBuffer buffer = new StringBuffer();
buffer.append("(").append(className).append(":").append(lineNumber).append(")");
buffer.append(methodName);
return buffer.toString();
}
private static void getMethodNames(StackTraceElement[] sElements) {
className = sElements[1].getFileName();
methodName = sElements[1].getMethodName();
lineNumber = sElements[1].getLineNumber();
}
//超長文本打印
public static void longError(String message) {
if (!DEBUG) return;
if (!TextUtils.isEmpty(message)) {
getMethodNames(new Throwable().getStackTrace());
Log.e(className, TOP_BORDER);
Log.i(className, HORIZONTAL_LINE + " " + createLog());
Log.i(className, MIDDLE_BORDER + " ");
byte[] bytes = message.getBytes();
int length = bytes.length;
if (length <= CHUNK_SIZE) {
String[] lines = message.split(System.getProperty("line.separator"));
for (String line : lines) {
Log.e(className, HORIZONTAL_LINE + " " + line);
}
} else {
for (int i = 0; i < length; i += CHUNK_SIZE) {
int count = Math.min(length - i, CHUNK_SIZE);
String[] lines = new String(bytes, i, count).split(System.getProperty("line.separator"));
for (String line : lines) {
Log.e(className, HORIZONTAL_LINE + " " + line);
}
}
}
Log.e(className, BOTTOM_BORDER);
}
}
//超長文本打印
public static void longInfo(String message) {
if (!DEBUG) return;
if (!TextUtils.isEmpty(message)) {
getMethodNames(new Throwable().getStackTrace());
Log.i(className, TOP_BORDER);
Log.i(className, HORIZONTAL_LINE + " " + createLog());
Log.i(className, MIDDLE_BORDER + " ");
byte[] bytes = message.getBytes();
int length = bytes.length;
if (length <= CHUNK_SIZE) {
String[] lines = message.split(System.getProperty("line.separator"));
for (String line : lines) {
Log.i(className, HORIZONTAL_LINE + " " + line);
}
} else {
for (int i = 0; i < length; i += CHUNK_SIZE) {
int count = Math.min(length - i, CHUNK_SIZE);
String[] lines = new String(bytes, i, count).split(System.getProperty("line.separator"));
for (String line : lines) {
Log.i(className, HORIZONTAL_LINE + " " + line);
}
}
}
Log.i(className, BOTTOM_BORDER);
}
}
public static void d(String msg) {
if (DEBUG) {
if (!TextUtils.isEmpty(msg)) {
getMethodNames(new Throwable().getStackTrace());
Log.d(className, createLog(msg));
}
}
}
public static void v(String msg) {
if (DEBUG) {
if (!TextUtils.isEmpty(msg)) {
getMethodNames(new Throwable().getStackTrace());
Log.d(className, createLog(msg));
}
}
}
public static void e(String msg) {
if (!TextUtils.isEmpty(msg)) {
getMethodNames(new Throwable().getStackTrace());
Log.d(className, createLog(msg));
}
}
public static void i(String msg) {
if (DEBUG) {
if (!TextUtils.isEmpty(msg)) {
getMethodNames(new Throwable().getStackTrace());
Log.d(className, createLog(msg));
}
}
}
public static void d(String tag, String msg) {
if (DEBUG) {
if (!TextUtils.isEmpty(msg)) {
// Log.d(tag, msg);
getMethodNames(new Throwable().getStackTrace());
Log.d(className, createLog(msg));
}
}
}
public static void v(String tag, String msg) {
if (DEBUG) {
if (!TextUtils.isEmpty(msg)) {
Log.d(tag, msg);
}
}
}
public static void e(String tag, String msg) {
if (!TextUtils.isEmpty(msg)) {
Log.d(tag, msg);
}
}
public static void i(String tag, String msg) {
if (DEBUG) {
if (!TextUtils.isEmpty(msg)) {
Log.d(tag, msg);
}
}
}
}
3、代碼解析
3.1、調用方法
/**
* 短文本打印調用方法
* @param view
*/
public void shortText(View view) {
HLogger.d("這是一條測試信息。這是一條測試信息");
}
/**
* 長文本打印調用方法
* @param view
*/
public void longText(View view) {
HLogger.longInfo("545345343132121102045402.102135435412.121234564651313210210214541321shksjadhsdhaskjhdaskfhcask" +
"dhaskdhakuhdoiauwdhaksncxkajsjhdkajshdaksjshdaksdhaskdhaskjdhaskjhdaksjhdaskjhdkahsfgbdajsfcnkjdanc," +
"dsnbcsdhjkfgvsdkjhfhgaksudhaouisdqodhaksdnbcaskjcbnkadsfhdksafhgiudshgfsdkjfnakcbnkajsdhaksufghakfhdasjkfsakjdhfudhaoui" +
"sdqodhaksdnbcaskjcbnkadsfhdksafhgiudshgfsdkjfnakcbnkajsdhaksufghakfhdasjkfsakjdhf" +
"udhaouisdqodhaksdnbcaskjcbnkadsfhdksafhgiudshgfsdkjfnakcbnkajsdhaksufghakfhdasjkfsakjdhf" +
"udhaouisdqodhaksdnbcaskjcbnkadsfhdksafhgiudshgfsdkjfnakcbnkajsdhaksufghakfhdasjkfsakjdhf" +
"udhaouisdqodhaksdnbcaskjcbnkadsfhdksafhgiudshgfsdkjfnakcbnkajsdhaksufghakfhdasjkfsakjdhf");
}
調用非常簡單,HLogger類支持的方法如下,可以傳入自己的TAG,也可以不傳入,代碼自動獲取打印日誌的類的類名作爲TAG。
- 網絡請求時,將請求信息及返回信息打印出來。會使用到長文本信息打印。以下是網絡請求攔截器中,我打印的請求信息。如效果圖中所示。
//打印請求信息,正式項目中可以註釋掉
RequestBody requestBody = request.body();
String body = null;
if (requestBody != null) {
Buffer buffer = new Buffer();
requestBody.writeTo(buffer);
body = buffer.readString(Charset.forName("UTF-8"));
}
HLogUtil.longInfo(String.format("發送請求\nmethod:%s\nurl:%s\nheaders: %sbody:%s",
request.method(), request.url(), request.headers(), body));
以下是返回信息
String result = responseBody.string();
HLogUtil.longInfo(result);
3.2、解析
- 通過Throwable的StackTrace,拿到當前類的類名、行號等信息。所以我們先通過這些信息封裝我們的log信息。
private static String className;
private static String methodName;
private static int lineNumber;
private static void getMethodNames(StackTraceElement[] sElements) {
className = sElements[1].getFileName();
methodName = sElements[1].getMethodName();
lineNumber = sElements[1].getLineNumber();
}
private static String createLog(String log) {
StringBuffer buffer = new StringBuffer();
buffer.append(methodName);
buffer.append("(").append(className).append(":").append(lineNumber).append(")");
buffer.append(log);
return buffer.toString();
}
調用打印。
Log.d(className, createLog(msg));
- 長文本信息打印,其實就是在短文本基礎上進行了長文本內容的分割打印,及展示方式的封裝。
//超長文本打印
public static void longInfo(String message) {
if (!DEBUG) return;
if (!TextUtils.isEmpty(message)) {
getMethodNames(new Throwable().getStackTrace());
//先打印橫線
Log.i(className, TOP_BORDER);
//再打印類名和行號及調用方法名
Log.i(className, HORIZONTAL_LINE + " " + createLog());
//再打印中間橫線
Log.i(className, MIDDLE_BORDER + " ");
byte[] bytes = message.getBytes();
int length = bytes.length;
//判斷文本內容長度
if (length <= CHUNK_SIZE) {
//短文本,再判斷文本內容是否有換行符
String[] lines = message.split(System.getProperty("line.separator"));
for (String line : lines) {
Log.i(className, HORIZONTAL_LINE + " " + line);
}
} else {
//長文本循環打印,每一行中判斷是否有換行符
for (int i = 0; i < length; i += CHUNK_SIZE) {
int count = Math.min(length - i, CHUNK_SIZE);
String[] lines = new String(bytes, i, count).split(System.getProperty("line.separator"));
for (String line : lines) {
Log.i(className, HORIZONTAL_LINE + " " + line);
}
}
}
Log.i(className, BOTTOM_BORDER);
}
}
3.3、注意
- 長文本打印方法中,文本切割長度我是設置的100字節長度,這個可以自由調整。就是這個屬性:
private static final int CHUNK_SIZE = 100;
- 長文本打印方法 ,如果內容中有換行符,也會自動換行。