如何通过J2V8在Java层监听JS对象属性的变更?
在Java/Kotlin层捕获V8对象属性变更通知
针对你给出的JS与Kotlin代码场景,当JS执行obj.width = 100时,要在Java层获取属性变更通知,核心是利用V8引擎的**Accessor(属性访问器)**机制,给目标V8对象的width属性绑定自定义的setter回调,具体实现如下:
调整Kotlin代码实现
修改Native类的getObj方法,在创建返回的V8Object时,为width属性注册getter和setter回调,当JS侧修改属性值时,会触发setter中的Java层逻辑:
val native = Native() val nativeV8Obj = V8Object(v8) nativeV8Obj.registerJavaMethod(native, "getObj", "getObj", emptyArray()) v8.add("Native", nativeV8Obj) // 注意:nativeV8Obj.close()不要在初始化阶段调用,否则后续JS无法访问Native对象 // nativeV8Obj.close() 需移到V8引擎销毁前执行 class Native { fun getObj(): V8Object { val v8Obj = V8Object(v8) // 注册width属性的访问器:getter负责返回值,setter捕获变更 v8Obj.registerAccessor( "width", // Getter回调:返回存储的实际值 V8FunctionCallback { receiver, _ -> receiver?.get("width_internal") ?: v8.createUndefined() }, // Setter回调:捕获属性变更,这里就是通知触发点 V8FunctionCallback { receiver, parameters -> val newValue = parameters?.first() // 用内部隐藏属性存储实际值,避免直接访问width导致循环调用 receiver?.set("width_internal", newValue) // 这里编写你的变更处理逻辑,比如打印日志、通知其他组件等 println("width属性已变更为: ${newValue?.toString()}") null }, false // 是否启用严格模式,按需设置 ) // 初始化width的默认值 v8Obj.set("width_internal", 0) return v8Obj } }
关键说明
- Accessor机制:V8的
registerAccessor方法允许为属性绑定自定义的读写逻辑,当JS侧对属性进行赋值操作时,会直接触发Java层的setter回调,从而实现变更通知。 - 内部存储属性:使用
width_internal作为实际值的存储容器,避免在getter/setter中直接访问width属性导致无限循环调用。 - 资源管理:注意不要在初始化阶段就调用
nativeV8Obj.close(),否则JS侧将无法访问Native对象;需在V8引擎销毁前统一关闭所有V8Object实例,防止内存泄漏。 - 多属性监听:如果需要监听多个属性,重复调用
registerAccessor为每个属性绑定对应的getter/setter即可。
内容的提问来源于stack exchange,提问作者boybeak
相关产品推荐
相关产品推荐

