String jsonEmpty = “”;
String jsonEmpty2 = “{}”;
String jsonNull = null;
Slog.json(jsonEmpty);
Slog.json(jsonEmpty2);
Slog.json(jsonNull);
String json = “{‘xyy1’:[{‘test1’:‘test1’},{‘test2’:‘test2’}],‘xyy2’:{‘test3’:‘test3’,‘test4’:‘test4’}}”;
Slog.json(json);
String jsonArray =
"{ ‘employees’: [ {‘firstName’:‘John’, ‘lastName’:‘Doe’}, {‘firstName’:‘Anna’, ‘lastName’:‘Smith’}, "
+ “{‘firstName’:‘Peter’, ‘lastName’:‘Jones’}]}”;
Slog.json(jsonArray);
json1
json2
打印xml字符串
String androidXml = “<?xml version=\\"1.0\\" encoding=\\"utf-8\\"?>\n” +
"
" package=\“com.sky.tools\” >\n" +
“\n” +
"
" android:name=\“.application.MainApplication\”\n" +
" android:allowBackup=\“true\”\n" +
" android:icon=\“@mipmap/ic_launcher\”\n" +
" android:label=\“@string/app_name\”\n" +
" android:roundIcon=\“@mipmap/ic_launcher_round\”\n" +
" android:supportsRtl=\“true\”\n" +
" android:theme=\“@style/AppTheme\” >\n" +
" \n" +
" \n" +
" \n" +
“\n” +
" \n" +
" \n" +
" \n" +
"
\n" +
“\n” +
"
";
Slog.xml(androidXml);
xml_log
打印对象
Slog 支持对对象的打印,其原理是给每个不同的对象类型添加对应的对象解析器,默认提供对数组,集合等解析,支持自定义对象解析器。
打印null对象
Slog.i(null);
Slog.i(“”);
null_object
打印数组对象
// 全局多维对象数组
private static Object[] objectsArray = new Object[]{
new boolean[]{false, true, true, false},
new String[][]{
new String[]{“22”, “23”, “24”},
new String[]{“123”, “456”, “789”}},
new int[][][]{new int[][]{
new int[]{666, 555, 444},
new int[]{111, 222, 333, 444}},
new int[][]{
new int[]{1, 2, 3, 4, 5, 6},
new int[]{7878, 6565, 84155, 7542, 0}}}};
// 打印对象数组
Object[] objectArray = new Object[1024];
for (int i = 0; i < objectArray.length; i++) {
objectArray[i] = i;
}
Slog.i(objectArray);
// 打印String
String[] stringArray = new String[1024];
for (int i = 1024; i < stringArray.length + 1024; i++) {
stringArray[i - 1024] = "is " + i;
}
Slog.i(stringArray);
// 打印int数组
int[] intArray = new int[1024];
for (int i = 2048; i < intArray.length + 2048; i++) {
intArray[i - 2048] = i;
}
Slog.i(intArray);
// 打印多维数组
Slog.i(objectsArray);
array_log
打印自定义对象解析器的对象
有如下一个Student类。
public class Student {
private int number;
private int age;
private String name;
private boolean isBoy;
public Student(int number, int age, String name, boolean isBoy){
this.number = number;
this.age = age;
this.name = name;
this.isBoy = isBoy;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean isBoy() {
return isBoy;
}
public int getNumber() {
return number;
}
}
自定义一个Student对象解析器,所有的对象解析器都必须要实现Parser接口。
public class StudentParser implements Parser {
@Override
public Class getParseType() {
return Student.class;
}
@Override
public String parseToString(Student student) {
return student.getName() + " is a " + student.getAge() + " years old " + (student.isBoy() ? “boy” : “girl”);
}
}
上面的parseToString将在解析对象时调用,由它返回被解析的对象最终要表示的字符串内容。
// 没有添加解析器之前
Student s = new Student(12345, 54, “sky”, true);
Slog.d(s);
// 添加解析器之后
Slog.addObjectParser(new StudentParser());
Slog.d(s);
object_parser
打印Collection对象
这里以Map举例。
// empty map
Map map = new HashMap<>();
Slog.d(map);
// int map
Map intMap = new ConcurrentHashMap<>();
intMap.put(1, 2);
intMap.put(1543, 2745867);
intMap.put(17687, 27678);
intMap.put(76781, 27678);
intMap.put(1786768, 26786);
Slog.d(intMap);
// Object Map
Map objectStringMap = new LinkedHashMap<>();
objectStringMap.put(new Object(), “11223786”);
objectStringMap.put(new Object(), “475775486”);
objectStringMap.put(new Object(), “7856874757”);
Slog.d(objectStringMap);
// student Map
map.put(12345, new Student(12345, 54, “sky”, true));
map.put(123456, new Student(123456, 56, “sky2”, true));
map.put(1234567, new Student(1234567, 15, “sky3”, true));
map.put(12345678, new Student(12345678, 25, “sky4”, true));
map.put(1234555, new Student(1234555, 35, “sky5”, true));
map.put(12345444, new Student(12345444, 45, “sky6”, true));
Slog.d(map);
// map itself
Map map1 = new Hashtable<>();
//noinspection CollectionAddedToSelf,unchecked
map1.put(map1, map1);
Slog.d(map1);
map_log
指定临时的配置项打印日志
前面的示例都是不修改输出配置项时打印的日志,但是在很多时候我们可能根据不同的场景,需要采用不同的日志输出配置。
除了前面说的使用Slog.getSetting()方法获取Setting对象之后,修改全局输出配置外,Slog框架还支持指定临时输出配置,只在下次当前线程打印日志时生效一次的方式更改日志输出效果。
具体包括以下几个方法。
Slog.t() // 指定下一次当前线程打印日志的tag,最终输出的日志的Tag组合为: prefixTag-tag
Slog.th() // 指定下一次当前线程打印日志是否显示线程信息
Slog.m() // 指定下一次当前线程打印日志显示的调用stack中方法的数目
Slog.o() // 指定下一次当前线程打印日志显示stack方法时的偏移值
Slog.s() // 指定下一次当前线程打印日志是否采用简单模式输出
上面的配置方法可以单个使用也可以组合使用。
单个使用
Slog.t(“custom22”).i(“set tag to custom”);
Slog.th(false).i(“hide the threadInfo”);
Slog.m(0).i(“test 0 method count print, so hide track”);
Slog.m(3).i(“test three method count println”);
Slog.o(1).i(“method offset 1”);
Slog.s(true).i(“set to simple mode”);
temp_setting_log
联合使用
Slog.s(false).t(“fiveSetting”).th(true).m(5).o(2).i(“this time set five temp setting for test”);
five_temp_setting_log
添加日志适配器
Slog框架目前只提供一个实现的日志适配器LogcatTree,本框架支持自定义日志适配器,所有的日志适配器都必须要继承Tree抽象类或者其子类,为了保证足够的扩展性,我们在Tree的接口中除了可以接收到封装处理好的日志之外,也可以对原始的日志数据进行处理。
自定义一个FileTree。
public class FileTree extends Tree {
// … 还有其他的方法也可以根据需要复写
// 处理对象类型的日志,注意该接口方法,也可以根据原始的`originalObject`参数进行自定义处理
@Override
protected void prepareObjectLog(int priority, String tag, String[] compoundMessages, @Nullable Object originalObject) {
super.prepareObjectLog(priority, tag, compoundMessages, originalObject);
}
// 处理String类型的日志,注意该接口方法,也可以根据原始的`originalMessage`参数进行自定义处理
@Override
protected void prepareStringLog(int priority, String tag, Throwable t, String[] compoundMessages, @Nullable String originalMessages, @Nullable Object… args) {
super.prepareStringLog(priority, tag, t, compoundMessages, originalMessages, args);
}
// 该方法为必须要实现的父类抽象方法
@Override
protected void log(int priority, String tag, String message) {
// … 省略代码将日志保存到文件中
}
}
将其添加到日志适配器列表中,以后就可以正常使用了。
Slog.plantTree(new FileTree());
注意: 在每个日志适配器中,我们可以根据需要最终自己确定将组装之后的日志或者原始日志如何处理。
自定义日志组装器
通过继承LogAssembler抽象类,我们可以实现自己定义的日志组装器。
public class SimpleLogAssembler extends LogAssembler {
@Override
protected void onFormatModeLogMethodStackTrace(List compoundMessagesList, int methodCount, int stackOffset,
StackTraceElement[] trace) {
for (int i = methodCount; i > 0; i–) {
int stackIndex = i + stackOffset;
if (stackIndex >= trace.length) {
continue;
}
//noinspection StringBufferReplaceableByString
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司19年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【算法合集】
【延伸Android必备知识点】
【Android部分高级架构视频学习资源】
**Android精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
" />
最后
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司19年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
[外链图片转存中…(img-86gh3GFS-1712680204991)]
【算法合集】
[外链图片转存中…(img-Bu2HS1Ed-1712680204991)]
【延伸Android必备知识点】
[外链图片转存中…(img-2b9Id2j1-1712680204991)]
【Android部分高级架构视频学习资源】
**Android精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!