敞开生长之旅!这是我参加「日新计划 12 月更文挑战」的第9天,点击检查活动概况

要想了解 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等需求的头文件。当前如下:

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

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、运转作用

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

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、线程、发动、功能监控。