kraken上手体验
阿里的kraken声称能直接用flutter渲染web形态的应用,不仅能实现动态化而且性能也非常不俗,这相当于一个小型浏览器了,于是立马体验了一下。
flutter: 2.0.0
OS: linux
kraken: main@77d74a62
当前的kraken还不支持dart的sound null safety
, 不过能以兼容模式运行(看看人家做的这迁移!)
按官网的介绍运行先是一坨匪夷所思的报错: 什么error input '... chai:^2.9'
,折腾半天才发现npm必须得用taobao的源,用nrm解决了,要是不搞web的非前端开发刚接触肯定是懵的。
接着是一个脚本错误,怎么也找不着android sdk的位置:
Error [ERR_UNHANDLED_ERROR]: Unhandled error. ({
uid: 2,
name: 'build-android-kraken-lib',
branch: false,
error: Error: ENOENT: no such file or directory, scandir '/Users/lindeer/Library/Android/sdk/ndk'
at Object.readdirSync (fs.js:1021:3)
at /Users/lindeer/WorkPlace/flutter/projects/kraken/scripts/tasks.js:399:25
at build-android-kraken-lib (/Users/lindeer/WorkPlace/flutter/projects/kraken/node_modules/undertaker/lib/set-task.js:13:15)
at bound (domain.js:413:15)
at runBound (domain.js:424:12)
at asyncRunner (/Users/lindeer/WorkPlace/flutter/projects/kraken/node_modules/async-done/index.js:55:18)
at processTicksAndRejections (internal/process/task_queues.js:75:11) {
errno: -2,
syscall: 'scandir',
code: 'ENOENT',
path: '/Users/lindeer/Library/Android/sdk/ndk',
domainThrown: true
},
duration: [ 0, 1176206 ],
time: 1617778189523
})
不用说这对非安卓的开发也是懵的;原来是因为脚本假定了android sdk的目录在$HOME/Library/Android/sdk
,但实际上目录应该取环境变量$ANDROID_HOME
或者$ANDROID_SDK_DIR
:
diff --git a/scripts/tasks.js b/scripts/tasks.js
index 499d98a6..20690042 100644
--- a/scripts/tasks.js
+++ b/scripts/tasks.js
@@ -391,6 +391,8 @@ task('build-android-kraken-lib', (done) => {
if (platform == 'win32') {
androidHome = path.join(process.env.LOCALAPPDATA, 'Android\Sdk');
+ } else if (platform == 'linux') {
+ androidHome = process.env.ANDROID_HOME;
} else {
androidHome = path.join(process.env.HOME, 'Library/Android/sdk')
}
顺便说一下因为用到了ndk也需要提前安装好ndk,版本在20.0.5594570以上,安装ndk:
$ANDROID_HOME/tools/bin/sdkmanager "ndk;20.0.5594570"
最终在目录$ANDROID_HOME/ndk/20.0.5594570/
下应该有二进制命令ndk-build
在运行官网的npm run build:bridge:android
命令之前最好也做如下的更改,作用主要是改一下获取包的仓库地址,类似npm更改源否则非常容易卡在下载环节让人非常抓狂,要是对安卓开发不熟悉很容易是懵的; 另外cmake的一个写法在linux上总是报错一并更改如下:
diff --git a/kraken/android/gradle/wrapper/gradle-wrapper.properties b/kraken/android/gradle/wrapper/gradle-wrapper.properties
index 01a286e9..41ff4cf2 100644
--- a/kraken/android/gradle/wrapper/gradle-wrapper.properties
+++ b/kraken/android/gradle/wrapper/gradle-wrapper.properties
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
+distributionUrl=https\://downloads.gradle-dn.com/artifactory/appproduct_dev_local/gradle/gradle-5.6.4-all.zip
diff --git a/kraken/example/android/build.gradle b/kraken/example/android/build.gradle
index e0d7ae2c..93782f98 100644
--- a/kraken/example/android/build.gradle
+++ b/kraken/example/android/build.gradle
@@ -1,7 +1,7 @@
buildscript {
repositories {
- google()
- jcenter()
+ maven { url 'https://maven.aliyun.com/repository/google' }
+ maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
}
dependencies {
@@ -11,8 +11,8 @@ buildscript {
allprojects {
repositories {
- google()
- jcenter()
+ maven { url 'https://maven.aliyun.com/repository/google' }
+ maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
}
}
diff --git a/kraken/example/android/gradle/wrapper/gradle-wrapper.properties b/kraken/example/android/gradle/wrapper/gradle-wrapper.properties
index 296b146b..39aaae73 100644
--- a/kraken/example/android/gradle/wrapper/gradle-wrapper.properties
+++ b/kraken/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
+distributionUrl=https\://downloads.gradle-dn.com/artifactory/appproduct_dev_local/gradle/gradle-5.6.4-all.zip
diff --git a/bridge/CMakeLists.txt b/bridge/CMakeLists.txt
index 5d00989b..d5c6816e 100644
--- a/bridge/CMakeLists.txt
+++ b/bridge/CMakeLists.txt
@@ -199,7 +199,7 @@ target_include_directories(kraken PRIVATE
${CMAKE_CURRENT_SOURCE_DIR} PUBLIC ./include)
target_link_libraries(kraken PRIVATE ${BRIDGE_LINK_LIBS})
-if (${CMAKE_BUILD_TYPE} STREQUAL "release" OR ${CMAKE_BUILD_TYPE} STREQUAL "relwithdebinfo")
+if ((${CMAKE_BUILD_TYPE} STREQUAL "release") OR (${CMAKE_BUILD_TYPE} STREQUAL "relwithdebinfo"))
## http://ptspts.blogspot.com/2013/12/how-to-make-smaller-c-and-c-binaries.html
### remove dynamic_cast and exceptions
target_compile_options(kraken PRIVATE -fno-exceptions -fvisibility=hidden)
运行kraken的example示例的时候最好改成
$ flutter devices
3 connected devices:
Pixel (mobile) • FA69G0304769 • android-arm64 • Android 10 (API 29)
Linux (desktop) • linux • linux-x64 • Linux
Chrome (web) • chrome • web-javascript • Google Chrome 87.0.4280.88
$ cd kraken/example
$ flutter run -v -d FA69G0304769
加-d
是为了指明设备,flutter现在支持多设备有时会自动选择web或者桌面,这时候控制台的输出对flutter不熟悉的开发又是懵的;-v
能比较详细的显示编译过程中的细节,如果有错误方便定位.比如flutter2.0会报如下错误但在控制台却可能啥也不输出:
[ ] - provide a 'noSuchMethod' implementation.
[ ] class ScrollPositionWithSingleContext extends ScrollPosition implements ScrollActivityDelegate {
[ ] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[ ] /opt/programs/flutter/packages/flutter/lib/src/rendering/viewport_offset.dart:96:12: Context: 'ViewportOffset.hasPixels' is
defined here.
[ ] bool get hasPixels;
[ ] ^^^^^^^^^
[ +302 ms] [
更改如下:
diff --git a/kraken/lib/src/gesture/scroll_position_with_single_context.dart b/kraken/lib/src/gesture/scroll_position_with_single_context.dart
index 29ffe2af..0717d321 100644
--- a/kraken/lib/src/gesture/scroll_position_with_single_context.dart
+++ b/kraken/lib/src/gesture/scroll_position_with_single_context.dart
@@ -74,6 +74,9 @@ class ScrollPositionWithSingleContext extends ScrollPosition implements ScrollAc
@override
AxisDirection get axisDirection => context.axisDirection;
+ @override
+ bool get hasPixels => false;
+
@override
double setPixels(double newPixels) {
assert(activity.isScrolling);
经历三个领域的懵圈之后应该是能够编译成功并运行kraken_example
在设备上了,运行示例是本地js文件kraken/example/assets/bundle.js
, 用flutter的devTools可以看到生成的的2个文本对象都是flutter控件:
然而输入介绍文章中的示例url根本无法运行!直接报如下错误:
[+14652 ms] E/flutter (21723): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: NoSuchMethodError: The method
'evalBundle' was called on null.
[ ] E/flutter (21723): Receiver: null
[ ] E/flutter (21723): Tried calling: evalBundle()
[ ] E/flutter (21723): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
[ ] E/flutter (21723): #1 _evalBundle (package:kraken/widget.dart:243:22)
[ ] E/flutter (21723): #2 Kraken.loadURL (package:kraken/widget.dart:75:5)
[ ] E/flutter (21723): <asynchronous suspension>
[ ] E/flutter (21723):
它的这个controller
是个getter,貌似是缓存:
KrakenController get controller {
return KrakenController.getControllerOfName(shortHash(this));
}
等异步回来之后再获取就为null了,改成持有也不行
diff --git a/kraken/lib/widget.dart b/kraken/lib/widget.dart
index b77f7de4..5daeedff 100644
--- a/kraken/lib/widget.dart
+++ b/kraken/lib/widget.dart
loadURL(String bundleURL) async {
if (bundleURL == null) return;
- await controller.unload();
- await controller.loadBundle(
+ final c = controller;
+ print("--------0 loadURL: $bundleURL");
+ await c.unload();
+ print("--------1 loadURL: $bundleURL");
+ await c.loadBundle(
bundleURL: bundleURL
);
- _evalBundle(controller, animationController);
+ print("--------2 loadURL: $bundleURL");
+ _evalBundle(c, animationController);
}
是用法不对吗,如果直接执行请求回来的js文本呢?也不行,报错如下:
[+16992 ms] E/flutter (22311): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: NoSuchMethodError: The method 'unload'
was called on null.
[ ] E/flutter (22311): Receiver: null
[ ] E/flutter (22311): Tried calling: unload()
[ ] E/flutter (22311): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
[ ] E/flutter (22311): #1 Kraken.loadContent (package:kraken/widget.dart:62:22)
[ ] E/flutter (22311): #2 _MyHomePageState.build.<anonymous closure> (package:kraken_example/main.dart:65:24)
[ ] E/flutter (22311): <asynchronous suspension>
[ ] E/flutter (22311):
很难说是不是因为flutter2.0的原因导致一些控件行为变化了,看来还有很多的适配工作,目前也没法再体验,难道要开发人员再回退flutter版本吗?!对于我一开始不想了解这太多细节,想立马上手看下效果都这般费劲……
国内的这些kpi开源就有这样的问题,文档不清不楚,预设假定的前提条件太多对开发人员实在是太不友好了;现在压根都不运行测试一下就他娘的开源,开开开,开你娘的屁。