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

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

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  4. \#include  5. \#include  6. \#include  7. \#include  8. \#include  9. \#include  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  5. \#include  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  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
", className); 12.   clazz = env->FindClass(className); 13.  14.   if (clazz == NULL) { 15. •    MY_LOGE("Native registration unable to find class '%s'
", className); 16. •    return JNI_ERR; 17.   } 18.   if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { 19. •    MY_LOGE("RegisterNatives failed for '%s'
", 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、运行效果


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、线程、启动、性能监控、以及framework框架的学习进阶。区分出来的知识点很多,我整理出如下知识导图:

根据这些知识脑图划分,我花费半个月时间整理出一套Flutter学习笔记,里面很详细归纳了各个知识点的重点,从基础介绍-技术点原理-源码分析-作用实战演练。

资料整理和思维脑图整理在这里:【私信我发送:“手册”获取】《Flutter3.0》

下面是一些PDF细分的学习知识点图解:

资料整理不易,还需大家多多支持;助力Android开发。咱们下期继续Android技术分享。

私信:“手册”获取全部资料!

Android路漫漫,关注多点赞!

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章