要想了解 Flutter,你必须先了解它的底层图像渲染引擎 Skia。因为,Flutter 只关心如何向 GPU 提供视图数据,而 Skia 就是它向 GPU 提供视图数据的好帮手。
Skia是一个用C++开发的开源的2D渲染引擎,支持多个硬件和软件平台。而且他是Google chrome, android, Flutter产品里面用到的图形引擎。
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. } XP+Eclipse+Cygwin。准备源码。
$WORKSPACE、$NDKROOT为工作空间、NDK路径。在Cygwin根目录\home\[your name]\ .bash_profile文件内配置。3.includes jni、skia等需要的头文件。当前如下:
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也可从模拟器导出。
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. } 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_ */ 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. } 使用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.exe2、添加当前工程下的头文件和库文件
添加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 条评论) “” |