首页 > 编程知识 正文

java反射和动态代理,java反射机制的底层原理

时间:2023-05-03 10:20:54 阅读:45998 作者:271

如何在Android平台上使用JavaScript直接调用Java方法

在Creator打包的Android本机APP中,可以使用反射机制在JavaScript中直接调用Java的静态方法。 它的使用很简单:

varo=jsb.reflection.callstaticmethod (class name,methodName,methodSignature,parameters . )

在callStaticMethod方法中,可以通过传递给Java的类名、方法名、方法签名和参数直接调用Java的静态方法,从而获取Java方法的返回值。 下面介绍的类名和方法的签名可能有点奇怪,但Java的规范就是这样的。

类名

参数中的类名必须是包含Java包路径的完整类名。 例如,我们在名为org.cocos2dx.javascript的包下编写了一个Test类。

package org.cocos2dx.javascript;

公共类测试{

publicstaticvoidhello (字符串msg ) {

system.out.println(msg;

}

公共静态Intsum (inta,int b ) {

返回a b;

}

公共静态防毒(inta ) {

返回a 2;

}

}

那么,此Test类的完整类名必须为org/cocos2dx/javascript/Test。 请注意,这里必须是正斜杠/,不是我们在Java代码中习惯的地方。

方法名称

方法名称很简单。 方法的原始名称。 例如,sum方法的名称为sum。

方法签名

方法签名有点复杂,但最简单的方法签名是(v,表示没有参数且没有返回值的方法。 其他示例:

) I ) v表示参数为一个int,无法返回值

(I ) I表示参数为1个int、返回值为int的方法

(IF ) z表示参数为int和float,返回值为boolean的方法

理解了几个吧? 括号中的符号表示参数类型,括号后的符号表示返回类型。 因为Java允许函数重载,所以有多个方法,即使方法名称相同,参数返回值也不同。 方法签名有助于区分这些同名的方法。

当前Cocos Creator支持以下四种类型的Java签名:

Java类型

签名

资讯科技

I

浮动

f

布尔型

z

史汀

Ljava/lang/String;

参数

参数可以是0个,也可以是多个。 直接使用JS的number、bool、string就可以了。

使用案例

调用上面Test类的静态方法。

调用hello方法

jsb.reflection.callstaticmethod (org/cocos2d x/JavaScript/test )、() hello )、() Ljava/lang/String; (v )、(this is a message from js );

//调用第一个sum方法

varresult=jsb.reflection.callstaticmethod ((org/cocos2d x/JavaScript/test )、() II )、I )、3、7

c .日志(结果); //10

//调用第二个sum方法

varresult=jsb.reflection.callstaticmethod ((org/cocos2d x/JavaScript/test )、() sum )、((I )、3 );

c .日志(结果); //5

在你的控制台上得到正确的输出。 这很简单吧。

注意

还有需要注意的事情。 在Android APP中,Cocos引擎的呈现和JS逻辑在GL线程中进行,但Android本身的UI更新在App的UI线程中进行,因此在JS调用的Java方法中更新UI的操作(如果有)将在UI线程中进行

例如,以下示例调用显示Android警报对话框的Java方法。

//请在我们熟悉的AppActivity类中加入一点东西

publicclassappactivityextendscocos2dx activity

{

private static AppActivity app = null;

@Override

public void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

app = this;

}

public static void showAlertDialog(final String title,final String message){

// 这里一定要使用 runOnUiThread

app.runOnUiThread(new Runnable() {

@Override

public void run(){

AlertDialog alertDialog = new AlertDialog.Builder(app).create();

alertDialog.setTitle(title);

alertDialog.setMessage(message);

alertDialog.setIcon(R.drawable.icon);

alertDialog.show();

}

});

}

}

然后我们在 JS 中调用:

jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "showAlertDialog", "(Ljava/lang/String;Ljava/lang/String;)V", "title", "hahahahha");

这样调用你就可以看到一个 Android 原生的 Alert 对话框了。

再加点料

现在我们可以从 JS 调用 Java 了,那么能不能反过来?当然可以!

在你的项目中包含 Cocos2dxJavascriptJavaBridge,这个类有一个 evalString 方法可以执行 JS 代码,它位于 frameworksjs-bindingsbindingsmanualplatformandroidjavasrcorgcocos2dxlib 文件夹下。我们将会给刚才的 Alert 对话框增加一个按钮,并在它的响应中执行 JS。和上面的情况相反,这次执行 JS 代码必须在 GL 线程中进行。

一般来说,目前引擎并未承诺多线程下的安全性,所以在开发过程中需要避免 JS 代码在其他线程被调用,以避免各种内存错误。

alertDialog.setButton("OK", new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int which){

// 一定要在 GL 线程中执行

app.runOnGLThread(new Runnable() {

@Override

public void run(){

Cocos2dxJavascriptJavaBridge.evalString("cc.log("Javascript Java bridge!")");

}

});

}

});

如果要在 C++ 中调用 evalString,我们可以参考下面的方式,确保 evalString 在 JS 引擎所在的线程被执行:

Application::getInstance()->getScheduler()->performFunctionInCocosThread([=](){

se::ScriptEngine::getInstance()->evalString(script.c_str());

});

这样在点击 OK 按钮后,你应该可以在控制台看到正确的输出。evalString 可以执行任何 JS 代码,并且它可以访问到你在 JS 代码中的对象。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。