先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
正文
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
结果输出如下:
System.out: JSEngine output - getValue : testKey System.out: JSEngine output - setValue : setKey ------> 获取到值了
-
1
-
2
方法测试 - 返回本地类
- 添加本地测试类
class TestObject{ private String name; private String address; TestObject(String name ,String address){ this.name = name; this.address = address; } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
- 为JSEngine添加方法 getObjectValue
public Object getObjectValue(Object keyStr){ System.out.println("JSEngine output - getObjectValue : " + keyStr.toString()); return new TestObject("小明","广州"); }
-
1
-
2
-
3
-
4
- allFunctions 添加 getObjectValue 声明
allFunctions = " var ScriptAPI = java.lang.Class.forName(\"" + JSEngine.class.getName() + "\", true, javaLoader);\n" + " var methodGetValue= ScriptAPI.getMethod(\"getValue\", [java.lang.String]);\n" + " function getValue(key) {\n" + " return methodGetValue.invoke(javaContext,key);\n" + " }\n" + " var methodSetValue=ScriptAPI.getMethod(\"setValue\",[java.lang.Object,java.lang.Object]);\n" + " function setValue(key,value) {\n" + " methodSetValue.invoke(javaContext,key,value);\n" + " }\n"+ " var methodGetObjectValue=ScriptAPI.getMethod(\"getObjectValue\",[java.lang.Object]);\n" + " function getObjectValue(key) {\n" + " return methodGetObjectValue.invoke(javaContext,key);\n" + " }\n";
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
- 修改执行语句,尝试获取 name属性的值
private String testjs = "var test = getObjectValue('objectKey');" + "setValue('testvalue',test.name);";
-
1
-
2
-
3
- 运行,发现无法获取到属性name的值
System.out: JSEngine output - setValue : testvalue ------> undefined
- 1
解决方案
思路:先将返回的对象转成字符串,再利用 javascript 的 eval 函数将字符串转成符合要求的对象
此时,需要修改 JSEngine 中的getObjectValue方法和 allFunctions 中的 getObjectValue 方法
//修改 JSEngine 中的getObjectValue方法 public String getObjectValue(Object keyStr){ System.out.println("JSEngine output - getObjectValue : " + keyStr.toString()); return new Gson().toJson(new TestObject("小明","广州"));//利用Gson 将 TestObject对象先转成String }
-
1
-
2
-
3
-
4
-
5
//修改 allFunctions 中的getObjectValue方法 " var methodGetObjectValue=ScriptAPI.getMethod(\"getObjectValue\",[java.lang.Object]);\n" + " function getObjectValue(key) {\n" + " var retStr = methodGetObjectValue.invoke(javaContext,key);\n" + " var ret = {};" + " eval('ret='+retStr);" + " return ret;" + " }\n";
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
仍执行以下语句
private String testjs = "var test = getObjectValue('objectKey');" + "setValue('testvalue',test.name);";
-
1
-
2
-
3
输出如下:可以看到能使用 .name 的形式获取到 name属性的值
System.out: JSEngine output - getObjectValue : objectKey System.out: JSEngine output - setValue : testvalue ------> 小明
-
1
-
2
反射构建js语句
通过上面可以看到,在JSEngine中每添加一个方法,在JS语句中也要对应多添加一个方法。而在js语句的编写过程中则需要注意多处细节,比较容易书写错误,所以能否自动生成js语句而不用每次都手写呢?
有的,利用注解和反射。
首先观察前面的js语句
每个本地方法在js中的定义主要包括两部分:
1、通过本地方法的方法名来获得该方法
var methodGetValue= ScriptAPI.getMethod(\"getValue\", [java.lang.String]);\n
- 1
2、自定义js方法(可重新命名),在js方法中调用本地方法的引用
function getValue(key) { return methodGetValue.invoke(javaContext,key); }
-
1
-
2
-
3
其他有差异的话则在于返回值类型为本地类对象时候的js方法的不同,如
function getObjectValue(key) { var retStr = methodGetObjectValue.invoke(javaContext,key); var ret = {}; eval('ret='+retStr); return ret; }
-
1
-
2
-
3
-
4
-
5
-
6
下面开始反射构建js语句
1、创建注解 JSAnnotation ,设定参数 returnObject ,用于区分上面所述的方法是否返回本地类对象。
/** * 注解 */ @Target(value = ElementType.METHOD) @Retention(value = RetentionPolicy.RUNTIME) public @interface JSAnnotation { boolean returnObject() default false;//是否返回对象,默认为false 不返回 }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
2、为方法添加注解
//本地java方法,声明注解 @JSAnnotation public void setValue(Object keyStr, Object o) { System.out.println("JSEngine output - setValue : " + keyStr.toString() + " ------> " + o.toString()); } //本地java方法,声明注解 @JSAnnotation public String getValue(String keyStr) { System.out.println("JSEngine output - getValue : " + keyStr.toString() ); return "获取到值了"; } //有返回本地类对象,则returnObject 设置为true @JSAnnotation(returnObject = true) function getObjectValue(key) { var retStr = methodGetObjectValue.invoke(javaContext,key); var ret = {}; eval('ret='+retStr); return ret; }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
3、利用注解生成js语句
/** * 通过注解自动生成js方法语句 */ private String getAllFunctions(){ String funcStr = " var ScriptAPI = java.lang.Class.forName(\"%s\", true, javaLoader);\n" ; Class cls = this.getClass(); for (Method method: cls.getDeclaredMethods()){ JSAnnotation an = method.getAnnotation(JSAnnotation.class); if (an == null ) continue; String functionName = method.getName(); String paramsTypeString ="";//获取function的参数类型 String paramsNameString = "";//获取function的参数名称 String paramsNameInvokeString = ""; Class [] parmTypeArray = method.getParameterTypes(); if (parmTypeArray != null && parmTypeArray.length > 0){ String[] parmStrArray = new String[parmTypeArray.length]; String[] parmNameArray = new String[parmTypeArray.length]; for (int i=0;i < parmTypeArray.length; i++){ parmStrArray[i] = parmTypeArray[i].getName(); parmNameArray[i] = "param" + i ; } paramsTypeString = String.format(",[%s]",TextUtils.join(",",parmStrArray)); paramsNameString = TextUtils.join(",",parmNameArray); paramsNameInvokeString = "," + paramsNameString; } Class returnType = method.getReturnType(); String returnStr = returnType.getSimpleName().equals("void") ? "" : "return";//是否有返回值 String methodStr = String.format(" var method_%s = ScriptAPI.getMethod(\"%s\"%s);\n",functionName,functionName,paramsTypeString); String functionStr = ""; if (an.returnObject()){//返回对象 functionStr = String.format( " function %s(%s){\n" + " var retStr = method_%s.invoke(javaContext%s);\n" + " var ret = {} ;\n" + " eval('ret='+retStr);\n" + " return ret;\n" + " }\n" ,functionName,paramsNameString,functionName,paramsNameInvokeString ); }else {//非返回对象 functionStr = String.format( " function %s(%s){\n" + " %s method_%s.invoke(javaContext%s);\n" + " }\n",functionName,paramsNameString,returnStr,functionName,paramsNameInvokeString ); } funcStr = funcStr + methodStr + functionStr; } return funcStr; }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
js自动生成的完整封装
public class JSEngine { private Class clazz; private String allFunctions ="";//js方法语句 public JSEngine(){ this.clazz = JSEngine.class; allFunctions = String.format(getAllFunctions(), clazz.getName());//生成js语法 } class TestObject{ private String name; private String address; TestObject(String name ,String address){ this.name = name; this.address = address; } } /** * 本地方法 - 返回本地类对象 * @param keyStr * @return */ @JSAnnotation(returnObject = true) public String getObjectValue(Object keyStr){ System.out.println("JSEngine output - getObjectValue : " + keyStr.toString()); return new Gson().toJson(new TestObject("小明","广州")); } /** * 本地java方法 * @param keyStr * @param o */ @JSAnnotation public void setValue(Object keyStr, Object o) { System.out.println("JSEngine output - setValue : " + keyStr.toString() + " ------> " + o.toString()); } /** * 本地java * @param keyStr * @return */ @JSAnnotation public String getValue(String keyStr) { System.out.println("JSEngine output - getValue : " + keyStr.toString() ); return "获取到值了"; } /** * 执行JS * @param js js执行代码 eg: "var v1 = getValue('Ta');setValue(‘key’,v1);" */ public void runScript(String js){ String runJSStr = allFunctions + "\n" + js;//运行js = allFunctions + js org.mozilla.javascript.Context rhino = org.mozilla.javascript.Context.enter(); rhino.setOptimizationLevel(-1); try { Scriptable scope = rhino.initStandardObjects(); ScriptableObject.putProperty(scope, "javaContext", org.mozilla.javascript.Context.javaToJS(this, scope));//配置属性 javaContext:当前类JSEngine的上下文 ScriptableObject.putProperty(scope, "javaLoader", org.mozilla.javascript.Context.javaToJS(clazz.getClassLoader(), scope));//配置属性 javaLoader:当前类的JSEngine的类加载器 rhino.evaluateString(scope, runJSStr, clazz.getSimpleName(), 1, null); } finally { org.mozilla.javascript.Context.exit(); } } /** * 通过注解自动生成js方法语句 */ private String getAllFunctions(){ String funcStr = " var ScriptAPI = java.lang.Class.forName(\"%s\", true, javaLoader);\n" ; Class cls = this.getClass(); for (Method method: cls.getDeclaredMethods()){ JSAnnotation an = method.getAnnotation(JSAnnotation.class); if (an == null ) continue; String functionName = method.getName(); String paramsTypeString ="";//获取function的参数类型 String paramsNameString = "";//获取function的参数名称 String paramsNameInvokeString = ""; Class [] parmTypeArray = method.getParameterTypes(); if (parmTypeArray != null && parmTypeArray.length > 0){ String[] parmStrArray = new String[parmTypeArray.length]; String[] parmNameArray = new String[parmTypeArray.length]; for (int i=0;i < parmTypeArray.length; i++){ parmStrArray[i] = parmTypeArray[i].getName(); parmNameArray[i] = "param" + i ; } paramsTypeString = String.format(",[%s]", TextUtils.join(",",parmStrArray)); paramsNameString = TextUtils.join(",",parmNameArray); paramsNameInvokeString = "," + paramsNameString; } Class returnType = method.getReturnType(); String returnStr = returnType.getSimpleName().equals("void") ? "" : "return";//是否有返回值 String methodStr = String.format(" var method_%s = ScriptAPI.getMethod(\"%s\"%s);\n",functionName,functionName,paramsTypeString); String functionStr = ""; if (an.returnObject()){//返回对象 functionStr = String.format( " function %s(%s){\n" + " var retStr = method_%s.invoke(javaContext%s);\n" + " var ret = {} ;\n" + " eval('ret='+retStr);\n" + " return ret;\n" + " }\n" ,functionName,paramsNameString,functionName,paramsNameInvokeString ); }else {//非返回对象 functionStr = String.format( " function %s(%s){\n" + " %s method_%s.invoke(javaContext%s);\n" + " }\n",functionName,paramsNameString,returnStr,functionName,paramsNameInvokeString ); } funcStr = funcStr + methodStr + functionStr; } return funcStr; } /** * 注解 */ @Target(value = ElementType.METHOD) @Retention(value = RetentionPolicy.RUNTIME) public @interface JSAnnotation { boolean returnObject() default false;//是否返回对象,默认为false 不返回 } }
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
最后
分享一份NDK基础开发资料
分享内容包括不限于高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
最后
分享一份NDK基础开发资料
[外链图片转存中…(img-DkqDgeXM-1713648733820)]
分享内容包括不限于高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-sFzBGxnf-1713648733820)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!