2021SC@SDUSC
Hippy项目源码分析第四周
layout/android/jni
JNI是什么?
JNI是Java Native Interface的缩写,通过使用Java本地接口书写程序,可以确保代码在不同的平台上方便移植,从java1.1开始,JNI标准成为java平台的一部分,它允许java代码和其他语言写的代码进行交互,JNI一开始是为了与本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其它编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台的可移植性,但是,有些情况下这样做是可以接受的,甚至是必须的,例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能,JNI标准至少要保证本地代码能工作在任何java虚拟机环境
FlexNode.h
#pragma once
//一个比较常用的C/C++预处理指令,只要在头文件最开始加入这条预处理指令,就能保证头文件只被编译一次
#include <jni.h>
#include "../../engine/Hippy.h"
#include "scoped_java_ref.h"
#define FLEX_NODE_MEM_FUN_GET_INCLUDE(type, name) \
type FlexNodeGet##name(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj)
#define FLEX_NODE_MEM_FUN_SET_INCLUDE(type, name) \
void FlexNodeSet##name(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, type name)
//define可以替换多行的代码关键是要在每个换行的时候加上一个‘\’
class FlexNode {
public:
HPNodeRef mHPNode;
FlexNode(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller);
void FlexNodeReset(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller);
// 通过JNI调用java方法 -----------------------------------------
void FlexNodeFree(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
void FlexNodeFreeRecursive(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
void FlexNodeInsertChild(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jlong childPointer,
jint indext);
void FlexNodeRemoveChild(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jlong childPointer);
void FlexNodeCalculateLayout(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jfloat width,
jfloat height,
const base::android::JavaParamRef<jlongArray>& nativeNodes,
const base::android::JavaParamRef<jobjectArray>& javaNodes,
jint direction);
void FlexNodeNodeMarkDirty(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
bool FlexNodeNodeIsDirty(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
void FlexNodeNodeSetHasMeasureFunc(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jboolean hasMeasureFunc);
void FlexNodeNodeSetHasBaselineFunc(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jboolean hasMeasureFunc);
void FlexNodemarkHasNewLayout(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
bool FlexNodehasNewLayout(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
void FlexNodemarkLayoutSeen(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, Width);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, Width);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, Height);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, Height);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, Left);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, Left);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, Top);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, Top);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, Right);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, Right);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, Bottom);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, Bottom);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, MarginLeft);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, MarginLeft);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, MarginTop);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, MarginTop);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, MarginRight);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, MarginRight);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, MarginBottom);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, MarginBottom);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, PaddingLeft);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, PaddingLeft);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, PaddingTop);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, PaddingTop);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, PaddingRight);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, PaddingRight);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, PaddingBottom);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, PaddingBottom);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, BorderLeft);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, BorderLeft);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, BorderTop);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, BorderTop);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, BorderRight);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, BorderRight);
FLEX_NODE_MEM_FUN_GET_INCLUDE(jfloat, BorderBottom);
FLEX_NODE_MEM_FUN_SET_INCLUDE(jfloat, BorderBottom);
private:
virtual ~FlexNode();
// DISALLOW_COPY_AND_ASSIGN(FlexNode);
};
bool RegisterFlexNode(JNIEnv* env);
JNIEnv* GetJNIEnv();
FlexNode.cpp
LayoutContext类
class LayoutContext {
public:
LayoutContext(jlongArray nativeNodes, jobjectArray javaNodes) {
// 1.设置HPNodes和java nodes的映射指针
jboolean isCopy = JNI_FALSE;
JNIEnv* env = GetJNIEnv();
jlong* flexNodes = env->GetLongArrayElements(nativeNodes, &isCopy);
jsize size = env->GetArrayLength(nativeNodes);
for (int i = 0; i < size; i++) {
HPNodeRef hpNode = _jlong2HPNodeRef(flexNodes[i]);
ASSERT(hpNode != nullptr);
node_ptr_index_map[hpNode] = i;
}
env->ReleaseLongArrayElements(nativeNodes, flexNodes, 0);
// 2.保存java数组
ASSERT(size == env->GetArrayLength(javaNodes));
jnode_arr = javaNodes;
}
base::android::ScopedJavaLocalRef<jobject> get(HPNodeRef node) {
JNIEnv* env = GetJNIEnv();
auto idx = node_ptr_index_map.find(node);
if (idx == node_ptr_index_map.end()) {
return base::android::ScopedJavaLocalRef<jobject>();
} else {
jobject java_object = env->GetObjectArrayElement(jnode_arr, idx->second);
return base::android::ScopedJavaLocalRef<jobject>(env, java_object);
}
}
private:
std::map<HPNodeRef, size_t> node_ptr_index_map;
jobjectArray jnode_arr;
};