Android KLog原始碼分析

來源:互聯網
上載者:User

標籤:git   contains   exception   tle   ++   put   XML   builder   _for   

Android KLog原始碼分析

    • Android KLog原始碼分析
        • 代碼結構
        • 詳細分析
          • BaseLog
          • FileLog
          • JsonLog
          • XmlLog
        • 核心檔案KLogjava分析
        • 遇到的問題

一直使用這個庫。但沒有細緻研究。今天就來研究一下。該庫的地址:

KLog,在這裡先感謝下作者。棒棒噠!

代碼結構

整個代碼的結構非常easy。例如以下:

library    klog        BaseLog.java        FileLog.java        JsonLog.java        XmlLog.java    KLog.java    KLogUtil.java

共六個檔案:

  • BaseLog.java,支援主要的log列印
  • FileLog.java。支援以檔案的形式儲存log
  • JsonLog.java,支援列印json對象和json數組
  • XmlLog.java,支援列印Xml形式的log
詳細分析BaseLog

兩個方法:

public class BaseLog {    private static final int MAX_LENGTH = 4000;    public static void printDefault(int type, String tag, String msg) {        int index = 0;        int length = msg.length();        int countOfSub = length / MAX_LENGTH;        if (countOfSub > 0) {// 超過指定長度,粉刺列印。這樣就避免了系統預設的log長度限制了            for (int i = 0; i < countOfSub; i++) {                String sub = msg.substring(index, index + MAX_LENGTH);                printSub(type, tag, sub);                index += MAX_LENGTH;            }            printSub(type, tag, msg.substring(index, length));// 列印餘數部分        } else {            printSub(type, tag, msg);        }    }    private static void printSub(int type, String tag, String sub) {        switch (type) {            case KLog.V:                Log.v(tag, sub);                break;            case KLog.D:                Log.d(tag, sub);                break;            case KLog.I:                Log.i(tag, sub);                break;            case KLog.W:                Log.w(tag, sub);                break;            case KLog.E:                Log.e(tag, sub);                break;            case KLog.A:                Log.wtf(tag, sub);                break;        }    }}

這裡突破了android系統的log字數限制,事實上就是超過字數限制後。採用分次列印的方法來列印,其它代碼不做分析,比較簡單。

FileLog

三個方法

public class FileLog {    private static final String FILE_PREFIX = "KLog_";    private static final String FILE_FORMAT = ".log";    /**     * @param tag             log tag     * @param targetDirectory log file save dir     * @param fileName        log file name     * @param headString      log file 檔案頭     * @param msg             log file log內容主體     */    public static void printFile(String tag, File targetDirectory, @Nullable String fileName, String headString, String msg) {        fileName = (fileName == null) ? getFileName() : fileName;        if (save(targetDirectory, fileName, msg)) {            Log.d(tag, headString + " save log success ! location is >>>" + targetDirectory.getAbsolutePath() + "/" + fileName);        } else {            Log.e(tag, headString + "save log fails !");        }    }    /**     * @param dic      log file save dir     * @param fileName og file name     * @param msg      log file log內容主體     * @return true if save success     */    private static boolean save(File dic, @NonNull String fileName, String msg) {        File file = new File(dic, fileName);        try {            OutputStream outputStream = new FileOutputStream(file);            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "UTF-8");            outputStreamWriter.write(msg);            outputStreamWriter.flush();            outputStream.close();            return true;        } catch (FileNotFoundException e) {            e.printStackTrace();            return false;        } catch (UnsupportedEncodingException e) {            e.printStackTrace();            return false;        } catch (IOException e) {            e.printStackTrace();            return false;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 當未設定檔案名稱時,隨機產生一個檔案名稱     *     * @return default file name     */    private static String getFileName() {        Random random = new Random();        return FILE_PREFIX + Long.toString(System.currentTimeMillis() + random.nextInt(10000)).substring(4) + FILE_FORMAT;    }}
JsonLog

JsonLog就更簡單了,僅僅有一個方法(本寶寶曾經還以為Json列印會非常麻煩呢)

public class JsonLog {    public static void printJson(String tag, String msg, String headString) {        String message;        try {            if (msg.startsWith("{")) {// 處理json對象                JSONObject jsonObject = new JSONObject(msg);                message = jsonObject.toString(KLog.JSON_INDENT);            } else if (msg.startsWith("[")) {// 處理json數組                JSONArray jsonArray = new JSONArray(msg);                message = jsonArray.toString(KLog.JSON_INDENT);            } else {                message = msg;            }        } catch (JSONException e) {            message = msg;        }        KLogUtil.printLine(tag, true);// 調用格式化方法        message = headString + KLog.LINE_SEPARATOR + message;        String[] lines = message.split(KLog.LINE_SEPARATOR);        for (String line : lines) {            Log.d(tag, "║ " + line);        }        KLogUtil.printLine(tag, false);// 調用格式化方法    }}
XmlLog

兩個方法:

public class XmlLog {    /**     * 列印xml     *     * @param tag        log tag     * @param xml        xml content     * @param headString 檔案頭     */    public static void printXml(String tag, String xml, String headString) {        if (xml != null) {            xml = XmlLog.formatXML(xml);            xml = headString + "\n" + xml;        } else {            xml = headString + KLog.NULL_TIPS;        }        KLogUtil.printLine(tag, true);        String[] lines = xml.split(KLog.LINE_SEPARATOR);        for (String line : lines) {            if (!KLogUtil.isEmpty(line)) {                Log.d(tag, "║ " + line);            }        }        KLogUtil.printLine(tag, false);    }    /**     * @param inputXML xml content     * @return 格式化後的xml String     */    private static String formatXML(String inputXML) {        try {            Source xmlInput = new StreamSource(new StringReader(inputXML));            StreamResult xmlOutput = new StreamResult(new StringWriter());            Transformer transformer = TransformerFactory.newInstance().newTransformer();            transformer.setOutputProperty(OutputKeys.INDENT, "yes");            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");            transformer.transform(xmlInput, xmlOutput);            return xmlOutput.getWriter().toString().replaceFirst(">", ">\n");        } catch (Exception e) {            e.printStackTrace();            return inputXML;        }    }}

細心的你會發現。不管是Json形式還是XML形式。調用的都是系統原生的方法來處理資料,因此又時候對熟悉熟悉java(或android)提供的方法還是非常方便的。哈哈。

上面用到的KLogUtil,例如以下:

public class KLogUtil {    public static boolean isEmpty(String line) {        return TextUtils.isEmpty(line) || line.equals("\n") || line.equals("\t") || TextUtils.isEmpty(line.trim());    }    public static void printLine(String tag, boolean isTop) {        if (isTop) {            Log.d(tag, "╔═══════════════════════════════════════════════════════════════════════════════════════");        } else {            Log.d(tag, "╚═══════════════════════════════════════════════════════════════════════════════════════");        }    }}
核心檔案KLog.java分析

給方法主要提供了相似於系統log方法的不同重載,比較簡單,我這裡要講的是那個擷取log詳細有關的類名、方法名、行號等。與之相關的就是wrapperContent這種方法了。

private static String[] wrapperContent(int stackTraceIndex, String tagStr, Object... objects) {        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();        StackTraceElement targetElement = stackTrace[stackTraceIndex];        String className = targetElement.getClassName();// 得到類名        String[] classNameInfo = className.split("\\.");// 第一種形式        if (classNameInfo.length > 0) {            className = classNameInfo[classNameInfo.length - 1] + SUFFIX;        }        if (className.contains("$")) {//另外一種形式            className = className.split("\\$")[0] + SUFFIX;        }        String methodName = targetElement.getMethodName();//得到方法名        int lineNumber = targetElement.getLineNumber();//得到所在的行號        if (lineNumber < 0) {            lineNumber = 0;        }        String tag = (tagStr == null ? className : tagStr);        if (mIsGlobalTagEmpty && TextUtils.isEmpty(tag)) {            tag = TAG_DEFAULT;        } else if (!mIsGlobalTagEmpty) {            tag = mGlobalTag;        }        // 得到訊息主體        String msg = (objects == null) ? NULL_TIPS : getObjectsString(objects);        String headString = "[ (" + className + ":" + lineNumber + ")#" + methodName + " ] ";        return new String[]{tag, msg, headString};    }/**     * 得到訊息主體     *     * @param objects 訊息對象數組     * @return 訊息主體字串     */    private static String getObjectsString(Object... objects) {        if (objects.length > 1) {            StringBuilder stringBuilder = new StringBuilder();            stringBuilder.append("\n");            for (int i = 0; i < objects.length; i++) {                Object object = objects[i];                if (object == null) {                    stringBuilder.append(PARAM).append("[").append(i).append("]").append(" = ").append(NULL).append("\n");                } else {                    stringBuilder.append(PARAM).append("[").append(i).append("]").append(" = ").append(object.toString()).append("\n");                }            }            return stringBuilder.toString();        } else {            Object object = objects[0];            return object == null ?

NULL : object.toString(); } }

分析完成,是不是非常easy,假設你看了這個庫的代碼。你會認為我的分析都是多餘的。

遇到的問題

在使用KLog列印json形式資訊時。假設網路請求時非同步,會導致KLog.json列印的格式出現錯亂。即一個結果還沒有全然列印出來。裡外一個就開始列印了,這個應該是並發導致的問題,之後我會在KLog的基礎上對這個問題進行最佳化的。

Android KLog原始碼分析

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.