前言导读
各位同学大家好,最近在研究的鸿蒙的组件化。所以就想研究下反射机制 参考了安卓的里面的一些思路。所以写一个案例,现在分享给大家。废话不多说我们正式开始。
官方说明
ArkTS可以通过动态import的方式实现反射功能,通过类名和方法名调用类中的静态成员函数和实例成员函数
为什么要用反射
我们经常会遇到一个问题 就是需求来回改动 ,今天要,明天不要 ,后又要 这样是不是很痛苦。我们不能改变需求方的想法,我们只能改变我们的自己思路。
-
把我们开发功能拆分成模块。
例如你现在接了一个Google 登录和 Facebook授权登录,我们是不是可以把这个整个授权模块抽离成一个module 我们只需要用反射调用,这样就不需要导包也可以调用到里面方法。如果现在这个项目需要这个功能 我们只需要把这个module 打包成(Android aar )/(鸿蒙 har或者hap) 然后依赖到主工程里面。如果不需要,我们责不需要这个打包后的 (Android aar /鸿蒙 har或者hap) 我们调用的时候扫描到不存我们调用的类就直接走 catch 即可
安卓的实现逻辑
这里先用安卓的做个示例 后面有arkts 版本的讲解
-
被调用的方法 openActivity
package com.zcehzgr.hawdmoab;
import android.app.Activity;
import android.util.Log;
/***
*
*
* 创建人:xuqing
* 创建时间:2025年4月3日17:47:09
*
*/
public class TestOpenController {
private static final String TAG = "TpController";
private static TestOpenController instacne=null;
public static TestOpenController getInstance(){
if(instacne==null){
synchronized (TestOpenController.class){
if(instacne==null){
instacne=new TestOpenController();
}
}
}
return instacne;
}
/***
*
* 打开activity 的方法
* @param activity
* @param
*/
public void openActivity(Activity activity,int code , String msg){
Log.e(TAG, "openActivity:code "+code +"msg -- > "+msg );
}
}
-
反射调用
package com.example.myapplication;
import android.app.Activity;
import android.util.Log;
import java.lang.reflect.Method;
public class TestPluginFactory {
private final String TAG = getClass().toString();
Class singletonClass;//类
Object singletonInstence;//单例对象
private static TestPluginFactory mInstance;
private TestPluginFactory() {
}
public static TestPluginFactory getInstance(){
if(mInstance == null){
mInstance = new TestPluginFactory();
}
return mInstance;
}
public void initPlugin(){
try {
singletonClass = Class.forName("com.zcehzgr.hawdmoab.TestOpenController");
Log.e(TAG, "initPlugin:singletonClass "+singletonClass);
if(null !=singletonClass){
Method getInstenceMethod = singletonClass.getDeclaredMethod("getInstance");
singletonInstence = getInstenceMethod.invoke(null);
}
}catch (Throwable e){
Log.e(TAG,"clwuysingletonClass initPlugin e"+e.toString());
}
}
public boolean iClassAndSingletonHave(){
if (singletonClass == null){
Log.e(TAG,"clwuysingletonClass null");
return false;
}
if (singletonInstence==null){
Log.e(TAG," clwuysingletonInstence null");
return false;
}
return true;
}
/***
*
*
* 反射去调用我们的 openActivity
* @param activity
* @param code
* @param msg
*
*/
public void openTestActivity(Activity activity,int code , String msg){
Log.e(TAG,"clwuyinit:"+TAG);
if(!iClassAndSingletonHave()){
return;
}
try {
Log.e(TAG, "code: "+code );
Log.e(TAG, "msg: "+msg );
Method initMethod = singletonClass.getDeclaredMethod("openActivity",Activity.class,int.class,String.class);
initMethod.invoke(singletonInstence,activity,code,msg);
}catch (Throwable e){
Log.e(TAG,"openTp e"+e.toString());
}
}
}
初始化我们反射插件类和调用 openTestActivity
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import com.example.namespace.R;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TestPluginFactory.getInstance().initPlugin();
findViewById(R.id.main_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TestPluginFactory.getInstance().openTestActivity(MainActivity.this,0,"测试数据局");
}
});
}
}
-
查看日志
我们通过日志可以看到 我们已经用反射调用到我们的 openActivity 方法了。
鸿蒙next arkts 反射实现
-
创建我们的library
如果不会创建是依赖可以看我之前的文章鸿蒙next 开发三方库重磅来袭
定义我们需要调用的方法
// harlibrary's src/main/ets/utils/Calc.ets
export class Calc {
public static staticAdd(a:number, b:number):number {
let c = a + b;
console.info('DynamicImport I am harlibrary in staticAdd, %d + %d = %d', a, b, c);
return c;
}
public instanceAdd(a:number, b:number):number {
let c = a + b;
console.info('DynamicImport I am harlibrary in instanceAdd, %d + %d = %d', a, b, c);
return c;
}
}
export function addHarlibrary(a:number, b:number):number {
let c = a + b;
console.info('DynamicImport I am harlibrary in addHarlibrary, %d + %d = %d', a, b, c);
return c;
}
-
在我们的mylibaray里面的Index.ets里面注册
export { Calc, addHarlibrary } from './src/main/ets/components/Calc'
然后在我们的 entry 的index里面测试调用
aboutToAppear(): void {
try{
// HAP's src/main/ets/pages/Index.ets
import('mylibrary').then((ns:ESObject) => {
// ns.Calc.staticAdd(8, 9); // 调用静态成员函数staticAdd()
// let calc:ESObject = new ns.Calc(); // 实例化类Calc
// calc.instanceAdd(10, 11); // 调用成员函数instanceAdd()
// ns.addHarlibrary(6, 7); // 调用全局方法addHarlibrary()
// 使用类、成员函数和方法的字符串名字进行反射调用
let className = 'Calc';
let methodName = 'instanceAdd';
let staticMethod = 'staticAdd';
let functionName = 'addHarlibrary';
ns[className][staticMethod](12, 13); // 调用静态成员函数staticAdd()
let calc1:ESObject = new ns[className](); // 实例化类Calc
calc1[methodName](14, 15); // 调用成员函数instanceAdd()
ns[functionName](16, 17); // 调用全局方法addHarlibrary()
});
}catch (e) {
console.log("反射调用失败")
}
}
index 完整代码
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
aboutToAppear(): void {
try{
// HAP's src/main/ets/pages/Index.ets
import('mylibrary').then((ns:ESObject) => {
// ns.Calc.staticAdd(8, 9); // 调用静态成员函数staticAdd()
// let calc:ESObject = new ns.Calc(); // 实例化类Calc
// calc.instanceAdd(10, 11); // 调用成员函数instanceAdd()
// ns.addHarlibrary(6, 7); // 调用全局方法addHarlibrary()
// 使用类、成员函数和方法的字符串名字进行反射调用
let className = 'Calc';
let methodName = 'instanceAdd';
let staticMethod = 'staticAdd';
let functionName = 'addHarlibrary';
ns[className][staticMethod](12, 13); // 调用静态成员函数staticAdd()
let calc1:ESObject = new ns[className](); // 实例化类Calc
calc1[methodName](14, 15); // 调用成员函数instanceAdd()
ns[functionName](16, 17); // 调用全局方法addHarlibrary()
});
}catch (e) {
console.log("反射调用失败")
}
}
build() {
RelativeContainer() {
Text(this.message)
.id('HelloWorld')
.fontSize($r('app.float.page_text_font_size'))
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.onClick(() => {
this.message = 'Welcome';
})
}
.height('100%')
.width('100%')
}
}
我们通过观察日志 和我们的index 代码我们并没improt 导入 Calc这个类 但是我们通过反射还是成功调用了
Calc 下面的 staticAdd instanceAdd addHarlibrary 三个方法。
最后总结:
有了这种反射调用机制,我们就可以让我们的模块化开发得以实现,我们可以在不同的模块之间使用 反射去调用,当然我们 项目在组装功能的时候 不需要某个功能,只需要把当前模块不打包成har 或者hap即可, 这样就方便去应对需求的不断改变的情况。今天的文章就讲到这里了,有兴趣的同学可以拿老师代码去优化修改, 今天的文章就讲到这里有兴趣的 关注我B站教程 了解更多鸿蒙开发的知识 可以关注坚果派公众号 。 谢谢
课程地址
项目内容:
-
1 常用布局组件的学习
-
2 网络请求工具类封装
-
3 arkui 生命周期启动流程
-
4 日志工具类的封装
-
5 自定义组合组件的封装
-
6 路由导航跳转的使用
-
7 本地地数据的缓存 以及缓存工具类的封装
-
8 欢迎页面的实现
-
9 登录案例和自动登录效果实现
-
10 请求网络数据分页上拉加载 下拉刷新的实现
-
11 list数据懒加载实现
-
12 webview组件的使用
如果使用更多好用的鸿蒙next三方库
友情链接
harmony-utils 一款功能丰富且极易上手的HarmonyOS工具库,借助众多实用工具类,致力于助力开发者迅速构建鸿蒙应用,能够满足各种不同的开发需求。
harmony-dialog 一款极为简单易用的零侵入弹窗,仅需一行代码即可轻松实现,无论在何处都能够轻松弹出。