阅读 84

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

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


作者:慢慢529
链接:https://juejin.cn/post/7171314612871102495

文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐