美文网首页
Flutter启动流程(Skia引擎)介绍与使用

Flutter启动流程(Skia引擎)介绍与使用

作者: 小城哇哇 | 来源:发表于2022-11-28 21:38 被阅读0次

要想了解 Flutter,你必须先了解它的底层图像渲染引擎 Skia。因为,Flutter 只关心如何向 GPU 提供视图数据,而 Skia 就是它向 GPU 提供视图数据的好帮手。

Skia是一个用C++开发的开源的2D渲染引擎,支持多个硬件和软件平台。而且他是Google chrome, android, Flutter产品里面用到的图形引擎。

Skia简单应用

1、Java外壳

1. public class SkiaView extends View { 
2.  
3.   /** TAG标识 */ 
4.   private static final String TAG = "SkiaView"; 
5.  
6.   /** 载入动态库 */ 
7.   static { 
8. •    try { 
9. •      System.loadLibrary("SkiaJni"); 
10. •    } catch(UnsatisfiedLinkError e) { 
11. •      Log.e(TAG, "Couldn't load native libs"); 
12. •      e.printStackTrace(); 
13. •    } 
14.   } 
15.  
16.   public SkiaView(Context context) { 
17. •    super(context); 
18.   } 
19.  
20.   @Override 
21.   protected void onDraw(Canvas canvas) { 
22. •    super.onDraw(canvas); 
23. •    Log.i(TAG, "==draw start=="); 
24. •    // 调用本地方法 
25. •    native_renderCanvas(canvas); 
26. •    Log.i(TAG, "==draw end=="); 
27.   } 
28.  
29.   /** 本地渲染画布方法 */ 
30.   private native void native_renderCanvas(Canvas canvas); 
31.  
32. } 

2、C/C++封装

2.1我的环境

XP+Eclipse+Cygwin。准备源码。

2.2建立工程

  1. 工程地址:AndroidSkia工程根目录jni文件夹。
  2. Build command:bash --login -c "cd WORKSPACE/AndroidSkia && NDKROOT/ndk-build"
     $WORKSPACE、$NDKROOT为工作空间、NDK路径。在Cygwin根目录\home[your name]\ .bash_profile文件内配置。

3.includes jni、skia等需要的头文件。当前如下:

image.png

2.3Android.mk


1. LOCAL_PATH := $(call my-dir) 
2. include $(CLEAR_VARS) 
3.  
4. MY_ANDROID_SOURCE = F:/01.软件/01.开发/05.android/android_sys_src/2.3.3_r1 
5. MY_ANDROID_SYSLIB = $(MY_ANDROID_SOURCE)/out/target/product/generic/system/lib 
6. #也可以在cygwin\home\Join.bash_profile文件内配置,如下: 
7. #  export MY_ANDROID_SOURCE="/cygdrive/f/..." 
8. #  export MY_ANDROID_SYSLIB="/cygdrive/f/..." 
9.  
10. LOCAL_MODULE := libSkiaJni 
11. LOCAL_SRC_FILES := \ 
12.   jniLoad.cpp \ 
13.   org_join_skia_SkiaView.cpp 
14.  
15. LOCAL_C_INCLUDES := \ 
16.   $(MY_ANDROID_SOURCE)/dalvik/libnativehelper/include/nativehelper \ 
17.   $(MY_ANDROID_SOURCE)/frameworks/base/include \ 
18.   $(MY_ANDROID_SOURCE)/system/core/include \ 
19.   $(MY_ANDROID_SOURCE)/frameworks/base/native/include \ 
20.   $(MY_ANDROID_SOURCE)/frameworks/base/core/jni/android/graphics \ 
21.   $(MY_ANDROID_SOURCE)/external/skia/include/core \ 
22.   $(MY_ANDROID_SOURCE)/external/skia/include/config \ 
23.   $(MY_ANDROID_SOURCE)/external/skia/include/p_w_picpaths 
24. #同时在工程Properties->C/C++ General->Paths and Symbols属性内include相应文件目录 
25. #否则编程时找不到.h文件,不便写代码,但不会影响编译。而LOCAL_LDLIBS/LOCAL_LDFLAGS必需添加。 
26.  
27. #LOCAL_LDLIBS := -L$(MY_ANDROID_SYSLIB) -llog -ljnigraphics -lskia -landroid_runtime 
28. #也可以用以下方式指定so库 
29. LOCAL_LDFLAGS := \ 
30.   $(MY_ANDROID_SYSLIB)/liblog.so \ 
31.   $(MY_ANDROID_SYSLIB)/libjnigraphics.so \ 
32.   $(MY_ANDROID_SYSLIB)/libskia.so \ 
33.   $(MY_ANDROID_SYSLIB)/libskiagl.so \ 
34.   $(MY_ANDROID_SYSLIB)/libandroid_runtime.so 
35.  
36. include $(BUILD_SHARED_LIBRARY) 


LOCAL_C_INCLUDES的头文件路径,第一个是jni的,最后三是lskia的,倒数四是ljnigraphics的,其他为基础的(如llog,除了某一是landroid_runtime的,忘了哪个==)。

MY_ANDROID_SYSLIB也可从模拟器导出。

2.4org_join_skia_SkiaView.cpp


1. #include "jniLoad.h" 
2.  
3. #include <GraphicsJNI.h> 
4. #include <SkCanvas.h> 
5. #include <SkPaint.h> 
6. #include <SkRect.h> 
7. #include <SkColor.h> 
8. #include <SkTypes.h> 
9. #include <SkGraphics.h> 
10.  
11. static void drawFlag(SkCanvas* canv); 
12.  
13. static void native_renderCanvas(JNIEnv* env, jobject obj, jobject canvas) { 
14.   MY_LOGI("==c method start=="); 
15.  
16.   SkCanvas* canv = GraphicsJNI::getNativeCanvas(env, canvas); 
17.   if (!canv) { 
18. •    MY_LOGE("==canv is NULL=="); 
19. •    return; 
20.   } 
21.  
22.   canv->save(); 
23.   canv->translate(100, 100); 
24.   drawFlag(canv); 
25.   canv->restore(); 
26.  
27.   MY_LOGI("==c method end=="); 
28. } 
29.  
30. /** 画旗帜 */ 
31. static void drawFlag(SkCanvas* canv) { 
32.   SkPaint* paint = new SkPaint(); 
33.   paint->setFlags(paint->kAntiAlias_Flag); 
34.  
35.   SkRect* rect = new SkRect(); 
36.   rect->set(0, 0, 200, 100); 
37.   paint->setColor(SK_ColorRED); 
38.   canv->drawRect(*rect, *paint); 
39.  
40.   paint->setColor(SK_ColorGRAY); 
41.   paint->setStrokeWidth(10); 
42.   canv->drawLine(5, 100, 5, 300, *paint); 
43.  
44.   paint->setTextSize(30); 
45.   paint->setColor(SK_ColorBLUE); 
46.   paint->setTextAlign(paint->kCenter_Align); 
47.   const char* text = "Hello World"; 
48.   canv->drawText(text, strlen(text), 100, 60, *paint); 
49. } 
50.  
51. /** 
52.  * JNI registration. 
53.  */ 
54. static JNINativeMethod methods[] = { { "native_renderCanvas", 
55. •    "(Landroid/graphics/Canvas;)V", (void*) native_renderCanvas } }; 
56.  
57. int register_org_join_skia_SkiaView(JNIEnv *env) { 
58.   return jniRegisterNativeMethods(env, "org/join/skia/SkiaView", methods, 
59. •      sizeof(methods) / sizeof(methods[0])); 
60. } 

2.5jniLoad.h

1. #ifndef JNILOAD_H_ 
2. #define JNILOAD_H_ 
3.  
4. #include <jni.h> 
5. #include <utils/Log.h> 
6.  
7. #define MY_LOG_TAG "JNI_LOG" 
8. #define MY_LOGI(...) __android_log_print(ANDROID_LOG_INFO, MY_LOG_TAG, __VA_ARGS__) 
9. #define MY_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, MY_LOG_TAG, __VA_ARGS__) 
10.  
11. #ifdef __cplusplus 
12. extern "C" { 
13. #endif 
14.  
15. int jniRegisterNativeMethods(JNIEnv* env, const char* className, 
16. •    const JNINativeMethod* gMethods, int numMethods); 
17.  
18. #ifdef __cplusplus 
19. } 
20. #endif 
21.  
22. #endif /* JNILOAD_H_ */ 

2.6jniLoad.cpp

1. #include "jniLoad.h" 
2.  
3. #include <stdlib.h> 
4.  
5. int register_org_join_skia_SkiaView(JNIEnv *env); 
6.  
7. int jniRegisterNativeMethods(JNIEnv* env, const char* className, 
8. •    const JNINativeMethod* gMethods, int numMethods) { 
9.  
10.   jclass clazz; 
11.   MY_LOGI("Registering %s natives\n", className); 
12.   clazz = env->FindClass(className); 
13.  
14.   if (clazz == NULL) { 
15. •    MY_LOGE("Native registration unable to find class '%s'\n", className); 
16. •    return JNI_ERR; 
17.   } 
18.   if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { 
19. •    MY_LOGE("RegisterNatives failed for '%s'\n", className); 
20. •    return JNI_ERR; 
21.   } 
22.   return JNI_OK; 
23. } 
24.  
25. jint JNI_OnLoad(JavaVM* vm, void* reserved) { 
26.   JNIEnv* env = NULL; 
27.   jint result = JNI_ERR; 
28.  
29.   if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { 
30. •    MY_LOGE("GetEnv failed!"); 
31. •    return result; 
32.   } 
33.  
34.   MY_LOGI("loading . . ."); 
35.  
36.   if(register_org_join_skia_SkiaView(env) != JNI_OK) { 
37. •    MY_LOGE("can't load org_join_skia_SkiaView"); 
38. •    goto end; 
39.   } 
40.   /** 
41.    * register others 
42.    */ 
43.  
44.   MY_LOGI("loaded"); 
45.  
46.   result = JNI_VERSION_1_4; 
47. end: 
48.   return result; 
49. } 

3、运行效果

image.png

Cygwin问题

使用Cygwin时可能遇到的问题,之前都没提到过,现在补上==。

1、make 3.81 bug - error: multiple target patterns. Stop.

[http://cygwin.com/ml/cygwin/2009-04/msg00007.html](https://cygwin.com/ml/cygwin/2009-04/msg00007.html)

•下载http://www.cmake.org/files/cygwin/make.exe替换原来的make.exe

2、添加当前工程下的头文件和库文件

添加include路径:project->properties->c/c++ build->settings->cygwin c compiler->includes->include paths->"${workspace_loc:/${ProjName}}"

•添加链接库:同上,在cygwin c linker->libraries下添加。

3、cygwin warning: MS-DOS style path detected:...

添加环境变量CYGWIN=nodosfilewarning,可取消报警。

文末到这里Flutter skia简单应用就介绍到这里。本文主要简介了Flutter学习中的启动流程的 skia引擎他,关于Flutter的学习,还需要学习很多知识点;它的基础语法dart、UI、线程、启动、性能监控。

本文转自 https://juejin.cn/post/7171314612871102495,如有侵权,请联系删除。

相关文章

网友评论

      本文标题:Flutter启动流程(Skia引擎)介绍与使用

      本文链接:https://www.haomeiwen.com/subject/mwerfdtx.html