一個(gè)可以過濾其他開發(fā)者日志的LogUtil工具類豆巨,團(tuán)隊(duì)開發(fā)中的你值得擁有!

只要你是程序員就一定熟悉這么一個(gè)東西掐场,那就是Log往扔。Log是我們?nèi)粘i_發(fā)中必不可少的調(diào)試工具贩猎,如果你是團(tuán)隊(duì)開發(fā)中的一員,那么就一定有過這樣的煩惱瓤球,那就是在調(diào)試過程中想要看你自己的日志的時(shí)候卻發(fā)現(xiàn)其他小伙伴的日志確異常的多融欧,很快就把你的日志頂沒了。
這篇帖子將解決你的煩惱卦羡。你可以根據(jù)需求選擇性的決定是否打印其他開發(fā)者的日志噪馏。(好了,下面進(jìn)入正題绿饵。)

首先奉上完整的代碼

public class LogUtil {

    /**
     * 表示過濾其他開發(fā)者日志欠肾。
     */
    private static final boolean FILTER_OTHER_DEVELOPER_LOG = true;
    /**
     * 表示輸出方法信息及位置。
     */
    private static final boolean LOG_METHOD_INFO = true;
    /**
     * 用來存放每個(gè)開發(fā)者的日志對象拟赊。
     */
    private static Hashtable<String, LogUtil> sLoggerTable = new Hashtable<String, LogUtil>();
    /**
     * 用來記錄當(dāng)前的開發(fā)者名稱刺桃。
     */
    private static String sCurDeveloperName;
    /**
     * 用來記錄當(dāng)前是否是debug模式。
     */
    private static boolean sIsDebug;
    /**
     * 用來記錄是否過濾其他開發(fā)者日志吸祟。
     */
    private static boolean sIsFilterOtherDeveloperLog;
    /**
     * 用來記錄是否打印日志所在的方法的信息瑟慈。
     */
    private static boolean sLogMethodInfo;
    /**
     * 用來記錄當(dāng)前的開發(fā)者。
     */
    private DEVELOPER mDeveloper;

    /**
     * 初始化函數(shù)屋匕。需要在Application啟動(dòng)的時(shí)候進(jìn)行初始化葛碧。
     *
     * @param developerName 開發(fā)者名稱,也是電腦名稱过吻。如果你的電腦沒有設(shè)置過名稱請?jiān)O(shè)置一下进泼。
     * @param isDebug       當(dāng)前是否是debug模式。true表示為debug模式纤虽,false表示為release模式乳绕。
     */
    public static void init(String developerName, boolean isDebug) {
        init(developerName, isDebug, LOG_METHOD_INFO);
    }

    /**
     * 初始化函數(shù)。需要在Application啟動(dòng)的時(shí)候進(jìn)行初始化逼纸。
     *
     * @param developerName 開發(fā)者名稱洋措,也是電腦名稱。如果你的電腦沒有設(shè)置過名稱請?jiān)O(shè)置一下杰刽。
     * @param isDebug       當(dāng)前是否是debug模式呻纹。
     * @param logMethodInfo 是否打印日志所處的方法的信息。true表示打印专缠,false表示不打印。默認(rèn)為true淑仆。
     */
    public static void init(String developerName, boolean isDebug, boolean logMethodInfo) {
        init(developerName, isDebug, logMethodInfo, FILTER_OTHER_DEVELOPER_LOG);
    }

    /**
     * 初始化函數(shù)涝婉。需要在Application啟動(dòng)的時(shí)候進(jìn)行初始化。
     *
     * @param developerName           開發(fā)者名稱蔗怠,也是電腦名稱墩弯。如果你的電腦沒有設(shè)置過名稱請?jiān)O(shè)置一下吩跋。
     * @param isDebug                 當(dāng)前是否是debug模式。
     * @param logMethodInfo           是否打印日志所處的方法的信息渔工。
     * @param filterOtherDeveloperLog 是否過濾其他開發(fā)者日志锌钮,如果為true表示你講看不到其他開發(fā)者的日志,false則可以引矩。默認(rèn)為true梁丘。
     */
    public static void init(String developerName, boolean isDebug, boolean logMethodInfo, boolean filterOtherDeveloperLog) {
        sCurDeveloperName = developerName;
        sIsDebug = isDebug;
        sLogMethodInfo = logMethodInfo;
        sIsFilterOtherDeveloperLog = filterOtherDeveloperLog;
    }

    /**
     * 定義一個(gè)開發(fā)者枚舉類,改類包含了開發(fā)者電腦名稱和開發(fā)者的日志標(biāo)識旺韭。
     */
    private enum DEVELOPER {

        /**
         * 定義開發(fā)者-Kelin氛谜。
         */
        KELIN("kelin", "@kelin@"),
        /**
         * 定義開發(fā)者-張三。
         */
        ZHANG_SAN("zhangsan", "@zhang@"),
        /**
         * 定義開發(fā)者-李四区端。
         */
        LISI("lisi", "@lisi@"),
        /**
         * 定義系統(tǒng)日志值漫,這個(gè)日志是所有開發(fā)者都能看到的。
         */
        SYSTEM("system", "@system@");

        private String name;
        private String value;

        /**
         * 構(gòu)造函數(shù)织盼。
         *
         * @param name  開發(fā)者的名稱杨何,也是電腦的名稱。
         * @param value 開發(fā)者的日志標(biāo)識沥邻,這個(gè)會(huì)顯示在日志中危虱。
         */
        DEVELOPER(String name, String value) {
            this.name = name;
            this.value = value;
        }

        /**
         * 獲取開發(fā)者名稱。
         */
        public String getName() {
            return name;
        }

        /**
         * 獲取開發(fā)者的日志標(biāo)識谋国。
         */
        public String getValue() {
            return value;
        }
    }

    /**
     * 獲取系統(tǒng)級別的日志工具槽地。
     */
    public static LogUtil getSystem() {
        return getLogger(DEVELOPER.SYSTEM);
    }

    /**
     * 獲取開發(fā)者Kelin的日志工具。
     */
    public static LogUtil getKelin() {
        return getLogger(DEVELOPER.KELIN);
    }

    /**
     * 獲取開發(fā)者張三的日志工具芦瘾。
     */
    public static LogUtil getZhangSan() {
        return getLogger(DEVELOPER.ZHANG_SAN);
    }

    /**
     * 獲取開發(fā)者李四的日志工具捌蚊。
     */
    public static LogUtil getLiSi() {
        return getLogger(DEVELOPER.LISI);
    }

    /**
     * 獲取一個(gè)開發(fā)者的日志工具。
     *
     * @param developer 開發(fā)者枚舉對象近弟。
     */
    private static LogUtil getLogger(DEVELOPER developer) {
        LogUtil logger = sLoggerTable.get(developer.getName());
        if (logger == null) {
            logger = new LogUtil(developer);
            sLoggerTable.put(developer.getName(), logger);
        }
        return logger;
    }

    /**
     * 構(gòu)造函數(shù)缅糟。
     *
     * @param developer 開發(fā)者枚舉對象。
     */
    private LogUtil(DEVELOPER developer) {
        this.mDeveloper = developer;
    }

    /**
     * 日志是否可以被顯示祷愉。
     *
     * @return 可以顯示返回true窗宦,不可以顯示返回false。
     */
    private boolean logCanDisplay() {
        if (sCurDeveloperName == null) {  //如果當(dāng)前開發(fā)者名稱為null說明沒有調(diào)用初始化方法二鳄,拋出異常赴涵,提示調(diào)用。
            throw new IllegalStateException("you must call init method int you application!");
        }
        // 只有系統(tǒng)和本人的日志才能輸出订讼,如果當(dāng)前不是Debug模式并且(不過濾其他開發(fā)者日志 或者 當(dāng)前開發(fā)者是日志打印者 或者 當(dāng)前日志是系統(tǒng)級別日志)
        return sIsDebug && (!sIsFilterOtherDeveloperLog || sCurDeveloperName.equalsIgnoreCase(mDeveloper.getName()) || DEVELOPER.SYSTEM.getName().equals(mDeveloper.getName()));
    }

    /**
     * 格式化Tag髓窜。
     *
     * @param tag 要格式化的Tag。
     * @return 返回格式化后的Tag。
     */
    @NonNull
    private String formatTag(String tag) {
        return String.format("%s[%s]:", TextUtils.isEmpty(tag) ? "" : tag, mDeveloper.getValue());
    }

    /**
     * 格式化Msg寄纵。
     *
     * @param msg 要格式化的Msg鳖敷。
     * @return 返回格式化后的Msg。
     */
    @NonNull
    private String formatMsg(@NonNull String msg) {
        return sLogMethodInfo ? String.format("%s ==> %s", msg, getFunctionName()) : msg;
    }

    public void i(@NonNull String msg) {
        i(null, msg);
    }

    public void i(String tag, @NonNull String msg) {
        if (logCanDisplay() && !TextUtils.isEmpty(msg)) {
            Log.i(formatTag(tag), formatMsg(msg));
        }
    }

    public void d(@NonNull String msg) {
        d(null, msg);
    }

    public void d(String tag, @NonNull String msg) {
        if (logCanDisplay() && !TextUtils.isEmpty(msg)) {
            Log.d(formatTag(tag), formatMsg(msg));
        }
    }

    public void e(@NonNull String msg) {
        e(null, msg);
    }

    public void e(String tag, @NonNull String msg) {
        e(tag, msg, null);
    }

    public void e(String tag, @NonNull String msg, Throwable e) {
        if (logCanDisplay() && !TextUtils.isEmpty(msg)) {
            if (e == null) {
                Log.e(formatTag(tag), formatMsg(msg));
            } else {
                Log.e(formatTag(tag), formatMsg(msg), e);
            }
        }
    }

    /**
     * 獲取當(dāng)前方法的詳細(xì)信息
     * 具體到方法名程拭、方法行定踱,方法所在類的文件名
     */
    private String getFunctionName() {
        StackTraceElement[] sts = Thread.currentThread().getStackTrace();
        if (sts == null) {
            return "";
        }
        for (StackTraceElement st : sts) {
            if (st.isNativeMethod()) {
                //本地方法native  jni
                continue;
            }
            if (st.getClassName().equals(Thread.class.getName())) {
                //線程
                continue;
            }
            if (st.getClassName().equals(this.getClass().getName())) {
                //構(gòu)造方法
                continue;
            }
            String[] split = st.getClassName().split("\\.");
            String className = split.length == 0 ? st.getClassName() : split[split.length - 1];
            return "[Thread: " + Thread.currentThread().getName() + " Class: "
                    + className + " Line:" + st.getLineNumber() + " Method: "
                    + st.getMethodName() + "]";
        }
        return "";
    }
}

下面再來講解一下,因?yàn)檫@個(gè)類你是不能直接拿來用的恃鞋。

  1. 定義枚舉內(nèi)部類崖媚。
   /**
    * 定義一個(gè)開發(fā)者枚舉類,改類包含了開發(fā)者電腦名稱和開發(fā)者的日志標(biāo)識山宾。
    */
   private enum DEVELOPER {

       /**
        * 定義開發(fā)者-Kelin至扰。
        */
       KELIN("kelin", "@kelin@"),
       /**
        * 定義開發(fā)者-張三。
        */
       ZHANG_SAN("zhangsan", "@張三@"),
       /**
        * 定義開發(fā)者-李四资锰。
        */
       LISI("lisi", "@李四@"),
       /**
        * 定義系統(tǒng)日志敢课,這個(gè)日志是所有開發(fā)者都能看到的。
        */
       SYSTEM("system", "@system@");

       private String name;
       private String value;

       /**
        * 構(gòu)造函數(shù)绷杜。
        * @param name 開發(fā)者的名稱直秆,也是電腦的名稱。
        * @param value 開發(fā)者的日志標(biāo)識鞭盟,這個(gè)會(huì)顯示在日志中圾结。
        */
       DEVELOPER(String name, String value) {
           this.name = name;
           this.value = value;
       }

       /**
        * 獲取開發(fā)者名稱。
        */
       public String getName() {
           return name;
       }

       /**
        * 獲取開發(fā)者的日志標(biāo)識齿诉。
        */
       public String getValue() {
           return value;
       }
   }

上面的DEVELOPER枚舉類是定義了開發(fā)者筝野,也就是說你的團(tuán)隊(duì)中有幾個(gè)人就需要定義幾個(gè)枚舉,DEVELOPER枚舉類中有兩個(gè)成員變量粤剧,分別為name和value(當(dāng)然歇竟,變量名你可以隨便定義。)抵恋,name為開發(fā)者的電腦名稱焕议,而value為開發(fā)者在日志中的標(biāo)識,你可以把它看做為昵稱弧关,它將顯示在日志中盅安。上面我是為我自己和Team中的張三和李四分別創(chuàng)建了枚舉。除此之外還有一個(gè)SYSTEM枚舉世囊,這個(gè)是系統(tǒng)級別的日志别瞭,如果你希望某個(gè)日志信息可以被所有小伙伴看到則需要打印此級別的日志。

  1. 定義獲取每個(gè)成員的LogUtil對象的靜態(tài)方法株憾。
   /**
    * 獲取系統(tǒng)級別的日志工具蝙寨。
    */
   public static LogUtil getSystem() {
       return getLogger(DEVELOPER.SYSTEM);
   }

   /**
    * 獲取開發(fā)者Kelin的日志工具。
    */
   public static LogUtil getKelin() {
       return getLogger(DEVELOPER.KELIN);
   }

   /**
    * 獲取開發(fā)者張三的日志工具。
    */
   public static LogUtil getZhangSan() {
       return getLogger(DEVELOPER.ZHANG_SAN);
   }

   /**
    * 獲取開發(fā)者李四的日志工具籽慢。
    */
   public static LogUtil getLiSi() {
       return getLogger(DEVELOPER.LISI);
   }

   /**
    * 獲取一個(gè)開發(fā)者的日志工具。
    * @param developer 開發(fā)者枚舉對象猫胁。
    */
   private static LogUtil getLogger(DEVELOPER developer) {
       LogUtil logger = sLoggerTable.get(developer.getName());
       if (logger == null) {
           logger = new LogUtil(developer);
           sLoggerTable.put(developer.getName(), logger);
       }
       return logger;
   }

這里的代碼就不解釋了箱亿,就是提供靜態(tài)方法讓小伙伴們獲取自己的日志工具類。

  1. 別忘了將構(gòu)造方法私有弃秆,因?yàn)榧热皇枪ぞ哳惥筒粦?yīng)該讓別人new出來用届惋。而是通過靜態(tài)方法獲取。
  2. 最后一點(diǎn)菠赚,有幾個(gè)重載的初始化方法別忘記了脑豹。
   /**
    * 初始化函數(shù)。需要在Application啟動(dòng)的時(shí)候進(jìn)行初始化衡查。
    *
    * @param developerName 開發(fā)者名稱瘩欺,也是電腦名稱。如果你的電腦沒有設(shè)置過名稱請?jiān)O(shè)置一下拌牲。
    * @param isDebug       當(dāng)前是否是debug模式俱饿。true表示為debug模式,false表示為release模式塌忽。
    */
   public static void init(String developerName, boolean isDebug) {
       init(developerName, isDebug, LOG_METHOD_INFO);
   }

   /**
    * 初始化函數(shù)拍埠。需要在Application啟動(dòng)的時(shí)候進(jìn)行初始化。
    *
    * @param developerName 開發(fā)者名稱土居,也是電腦名稱枣购。如果你的電腦沒有設(shè)置過名稱請?jiān)O(shè)置一下。
    * @param isDebug       當(dāng)前是否是debug模式擦耀。
    * @param logMethodInfo 是否打印日志所處的方法的信息棉圈。true表示打印,false表示不打印埂奈。默認(rèn)為true迄损。
    */
   public static void init(String developerName, boolean isDebug, boolean logMethodInfo) {
       init(developerName, isDebug, logMethodInfo, FILTER_OTHER_DEVELOPER_LOG);
   }

   /**
    * 初始化函數(shù)。需要在Application啟動(dòng)的時(shí)候進(jìn)行初始化账磺。
    *
    * @param developerName           開發(fā)者名稱芹敌,也是電腦名稱。如果你的電腦沒有設(shè)置過名稱請?jiān)O(shè)置一下垮抗。
    * @param isDebug                 當(dāng)前是否是debug模式氏捞。
    * @param logMethodInfo           是否打印日志所處的方法的信息。
    * @param filterOtherDeveloperLog 是否過濾其他開發(fā)者日志冒版,如果為true表示你講看不到其他開發(fā)者的日志液茎,false則可以。默認(rèn)為true。
    */
   public static void init(String developerName, boolean isDebug, boolean logMethodInfo, boolean filterOtherDeveloperLog) {
       sCurDeveloperName = developerName;
       sIsDebug = isDebug;
       sLogMethodInfo = logMethodInfo;
       sIsFilterOtherDeveloperLog = filterOtherDeveloperLog;
   }

這里也沒有什么好解釋的捆等,相信我的注釋還是比較詳細(xì)和簡單易懂的滞造。這三個(gè)只需要選擇一個(gè)適合你的在Application的onCreate方法中調(diào)用一次即可。
重點(diǎn)是這個(gè)電腦名稱應(yīng)該怎么給從哪里獲取這才是關(guān)鍵栋烤。(有的人想說谒养,直接看下電腦名稱然后寫死不就好了嗎?如果是這樣就不用提供方法在初始化的時(shí)候傳入了(*_* ) 明郭。)

獲取電腦名稱并調(diào)用初始化方法买窟。

獲取電腦名稱要在App的Gradle中的buildTypes{}下增加如下代碼:


//因?yàn)锽uildConfig.DEBUG有時(shí)候不是那么好用,所以自己寫一個(gè)薯定。
buildConfigField "boolean", "IS_DEBUG", "false"
//下面這句是獲取當(dāng)前的電腦名稱始绍。并為BuildConfig增加一個(gè)DEVELOPER_NAME字符串字段。
buildConfigField "String", "DEVELOPER_NAME", "\"${System.properties['user.name']}\""

上線的這兩句要分別加在release和debug節(jié)點(diǎn)下面话侄。下面是完整的buildTypes亏推。

    buildTypes {
        release {
            buildConfigField "boolean", "IS_DEBUG", "false"
            buildConfigField "String", "DEVELOPER_NAME", "\"${System.properties['user.name']}\""

            signingConfig signingConfigs.release
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            //…… 省略部分代碼
        }
        debug {
            buildConfigField "boolean", "IS_DEBUG", "true"
            buildConfigField "String", "DEVELOPER_NAME", "\"${System.properties['user.name']}\""

            signingConfig signingConfigs.release
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            //…… 省略部分代碼
        }
    }

完成上面的你就可以在Application中初始化了(別忘了在清單文件中使用你自定義的Application),代碼如下:

public class App extends MultiDexApplication {
    
    @Override
    public void onCreate() {
        super.onCreate();
        LogUtil.init(BuildConfig.DEVELOPER_NAME, BuildConfig.IS_DEBUG);
    }
}

好了現(xiàn)在一個(gè)工具類就完成了满葛,下面就一個(gè)使用了使用時(shí)你只需要通過靜態(tài)方法獲取自己的日志工具就可以了径簿,例如我要打印日志:LogUtil.getKelin().i("測試日志");現(xiàn)在其他的小伙伴是看不到你的日志信息的,除非在初始化的時(shí)候調(diào)用四個(gè)參數(shù)的方法嘀韧,并將第四個(gè)參數(shù)filterOtherDeveloperLog設(shè)置為false篇亭。


好了,今天的內(nèi)容到這里就結(jié)束了锄贷,如果你有什么問題译蒂、意見或建議請?jiān)谙路皆u論區(qū)留言交流。謝謝R耆础H嶂纭!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炎辨,一起剝皮案震驚了整個(gè)濱河市捕透,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碴萧,老刑警劉巖乙嘀,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異破喻,居然都是意外死亡虎谢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門曹质,熙熙樓的掌柜王于貴愁眉苦臉地迎上來婴噩,“玉大人擎场,你說我怎么就攤上這事〖该В” “怎么了迅办?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長章蚣。 經(jīng)常有香客問我礼饱,道長,這世上最難降的妖魔是什么究驴? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮匀伏,結(jié)果婚禮上洒忧,老公的妹妹穿的比我還像新娘。我一直安慰自己够颠,他們只是感情好熙侍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著履磨,像睡著了一般蛉抓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剃诅,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天巷送,我揣著相機(jī)與錄音,去河邊找鬼矛辕。 笑死笑跛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的聊品。 我是一名探鬼主播飞蹂,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼翻屈!你這毒婦竟也來了陈哑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤伸眶,失蹤者是張志新(化名)和其女友劉穎惊窖,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赚抡,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡爬坑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涂臣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盾计。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡售担,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出署辉,到底是詐尸還是另有隱情族铆,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布哭尝,位于F島的核電站哥攘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏材鹦。R本人自食惡果不足惜逝淹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望桶唐。 院中可真熱鬧栅葡,春花似錦、人聲如沸尤泽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坯约。三九已至熊咽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間闹丐,已是汗流浹背横殴。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留卿拴,地道東北人滥玷。 一個(gè)月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像巍棱,于是被迫代替她去往敵國和親惑畴。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,138評論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理航徙,服務(wù)發(fā)現(xiàn)如贷,斷路器,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法到踏,類相關(guān)的語法杠袱,內(nèi)部類的語法,繼承相關(guān)的語法窝稿,異常的語法楣富,線程的語...
    子非魚_t_閱讀 31,631評論 18 399
  • 想了一晚上的悄悄話,開口卻只成了早安伴榔。攢了一天的新鮮事纹蝴,開口卻又成了晚安庄萎。爸爸是那種五大三粗的人有一天晚上在我睡前...
    漠郴江閱讀 2,736評論 2 1
  • 鄭兒昨天晚上兩點(diǎn)鐘醒來哭著找neinei喝,我不給她喝打算戒掉夜奶塘安,她居然不依不饒哭了近一個(gè)小時(shí)糠涛,哭累了然后才睡著...
    簡寧思靜閱讀 289評論 0 0