2021SC@SDUSC

Hippy项目源码分析第四周

  • layout/android/jni
    • JNI是什么?
    • FlexNode.h
    • FlexNode.cpp

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;
};