使用C实现Android事件处理程序++

 2023-01-19    359  

问题描述

我在Java中有一个布局设计,我目前正在通过JNI移植到C ++.此时我实际上已经完成了,但是目前我对应该如何设置例如SetonClicklistener等活动处理程序感到困惑.我已经经过 jni Specification ,没有很多运气.

如果任何人都可以将以下片段移植到C ++或带领我朝正确的方向移植(由于结果的代码为多少),这将不胜感激.

使用C实现Android事件处理程序++

public void setOnClickListener(boolean modification, int index, int commandIndex, final TextView textView){
        final int key = index;
        final int command = commandIndex;
        if(modification) {
            textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    changingMenu(key, command, textView);
                    Runnable r = new Runnable() {
                        @Override
                        public void run() {
                            resetMenu(key, command, textView);
                        }
                    };

                    Handler h = new Handler();
                    h.postDelayed(r, 250);
                }
            });
            return;
        }
        menuTitle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                toggleMenu();
            }
        });
    }

编辑: 将不良论点传递给setOnClickListener

java

Object getProxy (MyInvocationHandler mih) {
    ClassLoader classLoader = new ClassLoader() {
        @Override
        public Class<?> loadClass(String name) throws ClassNotFoundException {
            return super.loadClass(name);
        }
    };
    return java.lang.reflect.Proxy.newProxyInstance(classLoader, new Class[] {  }, mih);
}

c ++

jobject createProxyInstance(JNIEnv *env, jclass cls, CFunc cfunc) {
    jclass cls_IH = env->FindClass("com/app/core/MyInvocationHandler");
    jmethodID cst_IH = env->GetMethodID(cls_IH, "<init>", "(J)V");
    jobject myIH = env->NewObject(cls_IH, cst_IH, (jlong)cfunc);

    jclass klass = env->FindClass("com/app/core/Activity");
    jmethodID method = env->GetMethodID(klass, "getProxy", "(Lcom/app/core/MyInvocationHandler;)Ljava/lang/Object;");
    return env->CallObjectMethod(context, method, myIH); //Returning wrong object?
}

jobject aa (JNIEnv *env, jobject obj, jobject proxy, jobject method, jobjectArray args) {
    __android_log_print(ANDROID_LOG_ERROR, "TEST", "SUCCESS");
}

void setListeners() {
    jclass klass = env->FindClass("android/view/View");
    jmethodID method = env->GetMethodID(klass, "setOnClickListener", "(Landroid/view/View$OnClickListener;)V");
    klass = env->FindClass("android/view/View$OnClickListener");
    env->CallVoidMethod(imageView, method, createProxyInstance(env, klass, &aa));
}

推荐答案

您显示的语法归结为在编译时创建匿名的内部类,并插入调用以创建这些类的对象(具有正确的变量范围内的对象),以代替new View.OnClickListener() { … } expression.

我看到以下两个选项:

  • 对于每个不同的接口,您可以创建一个实现接口的小Java类,并使用接口的方法实现native.这是最直接的方法,但是它确实需要您保持数十个或数百个接口实现.

  • 您使用java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)动态创建实现必要接口的对象.这将重新将每种方法调用到您的InvocationHandler实现,这应该是具有native Object invoke(Object proxy, Method method, Object[] args)实现的Java类.

    要使所有这些可重复使用,您可以实现此InvocationHandler来包装std::function对象,因此对EG menuTitle.setOnClickListener的最终调用可能看起来如下:

env->CallVoidMethod(menuTitle, menuTitle_setOnClickListener,
 createProxyInstance(env, cls_View_OnClickListener, [](JNIEnv *env, jobject proxy, jobject method, jobjectArray args) {
   ... 
});

对于后一种解决方案,定义以下Java类:

class MyInvocationHandler implements InvocationHandler {
  private long cfunc;
  MyInvocationHandler(long cfunc) { this.cfunc = cfunc; }
  public native static Object invoke(Object proxy, Method method, Object[] args);
}

您在C ++方面实现了:

typedef jobject (*CFunc)(JNIEnv *env, jobject obj, jobject proxy, jobject method, jobjectArray args)
extern "C" jobject Java_MyInvocationHandler_invoke(JNIEnv *env, jobject obj, jobject proxy, jobject method, jobjectArray args) {
  jclass cls_myIH = env->GetObjectClass(obj);
  jfieldID fld_myIH_cfunc = env->GetFieldID(cls_myIH, "cfunc", "J");
  CFunc cfunc = (CFunc)env->GetLongField(obj, fld_myIH_cfunc);
  cfunc(env, proxy, method, args);
  return nullptr;
}

最后,我们可以实现createProxyInstance如下:

jobject createProxyInstance(JNIEnv *env, jclass cls, CFunc cfunc) {
  jclass cls_IH = env->GetClass("MyInvocationHandler");
  jmethodID cst_IH = env->GetMethodID(cls_ID, "<init>", "(J)V");
  jobject myIH = env->NewObject(cls_ID, cst_IH, (jlong)cfunc);

  // now call Proxy.createProxyInstance with this object as InvocationHandler
}

以上所述是小编给大家介绍的使用C实现Android事件处理程序++,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!

原文链接:https://77isp.com/post/25815.html

=========================================

https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。