[Android] 使用函数指针实现 native 层异步回调,鸿蒙 app 开发工具
void EventManager::addEvent(EventEnum eventEnum, void* event, void* sender) {
if(event == nullptr || sender == nullptr) {
return;
}
EventData eventData;
eventData.eventPointer = event;
eventData.sender = sender;
eventMap.insert(std::pair<EventEnum, EventData>(eventEnum, eventData));
}
编写函数指针对应函数的具体实现
void eeSleepWakeCallback(int result, void* sender) {
JniTester *tester = (JniTester *) sender;
tester->onResultCallback(result);
}
在入口类中注册事件及其对应的枚举和函数
JniTester::JniTester() {
EventManager::getInstance().addEvent(eeSleepWake, (void*)eeSleepWakeCallback, this);
}
编写异步函数调用
··· void JniTester::getThreadResult() { ThreadTest *test = new ThreadTest(); test->sleepThread(); } ··· 耗时函数的具体实现:
void ThreadTest::sleepThread() {
std::thread cal_task(&ThreadTest::makeSleep, this);
cal_task.detach();
}
void ThreadTest::makeSleep() {
sleep(2);
}
这一步我们是通过新建一个线程,并让其等待 2S 来模拟异步耗时操作
[](
)4. 异步回调的实现
=========================================================================
在 java 层编写 java 的回调方法
private OnResultCallback callback;
public void setOnResultCallback(OnResultCallback callback) {
this.callback = callback;
}
public interface OnResultCallback {
void onResult(int result);
}
在 java 曾编写 java 层回调的触发:
public void onResult(int result) {
if (this.callback != null) {
callback.onResult(result);
}
}
native 层异步动作完成的通知
通过向单例的事件持有类获取对应的事件枚举,获取到其对应的函数指针,并调用该函数指针实现:
void ThreadTest::makeSleep() {
sleep(2);
EventData eventData = EventManager::singleton().getEventData(eeSleepWake);
onSleepWake wake = (onSleepWake)eventData.eventPointer;
if(wake) {
wake(12345, eventData.sender);
}
}
因为我们在第三章节第 7 步注册的函数指针是 eeSleepWakeCallback, 因此,这里会调用到这个函数:
void eeSleepWakeCallback(int result, void* sender) {
JniTester *tester = (JniTester *) sender;
tester->onResultCallback(result);
}
通过 sender 确定具体的对象,调用其 onResultCallback 函数
onResultCallback 函数的实现
void JniTester::onResultCallback(int result) {
JNIEnv *env = NULL;
int status = f_jvm->GetEnv((void **) &env, JNI_VERSION_1_4);
bool isInThread = false;
if (status < 0) {
isInThread = true;
f_jvm->AttachCurrentThread(&env, NULL);
}
if (f_cls != NULL) {
jmethodID id = env->GetMethodID(f_cls, "onResult", "(I)V");
if (id != NULL) {
env->CallVoidMethod(f_obj, id, result);
}
}
if (isInThread) {
f_jvm->DetachCurrentThread();
}
}
这里因为缺少 java 环境,因此我们需要将该线程挂载到 jvm 上执行,并获取对应的 JNIEnv ,通过 jnienv 获取 java 层的回调触发方法 onResult 并执行。
[](
)5.效果
==================================================================
编写测试代码:
JniTester tester = new JniTester();
Log.d("zyl", "startTime = " + System.currentTimeMillis());
tester.setOnResultCallback(result -> {
Log.d("zyl", "endTime = " + System.currentTimeMillis());
Log.d("zyl", "result = " + result);
});
评论