目前在尝试使用weex,但是在搭建基础的最小化项目的时候,官方文档描述的相当佛系,导致搭建出来的项目没办法正常运行。
下面我们探讨一下,使用`Android Studio 3.5.2`新建一个项目,实现最小化接入`weex 0.28.0`实践过程。
官方文档要求在项目的`build.gradle` 中增加如下内容:
implementation 'org.apache.weex:sdk:0.28.0@aar'
implementation 'com.alibaba:fastjson:1.2.62'
但是实际上,由于`weex 0.28.0`的调整,以前版本自动引入的`facebook`提供的`JS`引擎js-android,现在被修改为需要手工引入,但是文档没有清晰的指出这个问题,导致运行的时候,会由于找不到`libjsc.so`而导致`WXSDKEngine`初始化失败。
官方提供了一个`download_jsc.gradle`的脚本解决这个问题(这个脚本的功能仅仅是下载`libjsc.so` ),需要在项目的 `build.gradle` 的头部增加这个脚本文件的引用:
apply from: 'https://raw.githubusercontent.com/apache/incubator-weex/release/0.28/android/sdk/buildSrc/download_jsc.gradle'
如果下载不成功,也可从本站下载
apply from: 'https://www.mobibrw.com/wp-content/uploads/2019/11/download_jsc.gradle'
完成后的`build.gradle`中完整内容如下:
apply plugin: 'com.android.application'
apply from: 'https://raw.githubusercontent.com/apache/incubator-weex/release/0.28/android/sdk/buildSrc/download_jsc.gradle'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.mobibrw.weex"
minSdkVersion 22
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
abiFilters "armeabi","armeabi-v7a", "arm64-v8a", "x86"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.0.0'
implementation 'org.apache.weex:sdk:0.28.0@aar'
implementation 'com.alibaba:fastjson:1.2.62'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
接下来,就是具体的代码部分了,如下,需要自定义一个`Application`类,在`Application`的初始化部分初始化`WXSDKEngine`,代码如下:
package com.mobibrw.weex;
import android.app.Application;
import org.apache.weex.InitConfig;
import org.apache.weex.WXSDKEngine;
public class WeexApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
final InitConfig config = new InitConfig.Builder().build();
/**
* 底层的初始化是异步执行的,尤其是初始化JS引擎部分的代码(WXBridgeManager),是相当耗时的
* 因此,在调用完初始化之后,Activity第一次调用的时候,一定要增加是否已经初始化完成的判断
* 如果没有完成初始化,适当的增加延迟等待的代码
**/
WXSDKEngine.initialize(this, config);
}
}
接下来,就是具体的`Activity`内容展现代码部分了,代码如下:
package com.mobibrw.weex;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import org.apache.weex.IWXRenderListener;
import org.apache.weex.WXSDKEngine;
import org.apache.weex.WXSDKInstance;
import org.apache.weex.common.WXRenderStrategy;
public class MainActivity extends AppCompatActivity implements IWXRenderListener {
private WXSDKInstance wXSDKInstance;
private static final String TAG = "WXSampleTAG";
private void loadPages() {
/**
* bundleUrl source http://dotwe.org/vue/38e202c16bdfefbdb88a8754f975454c
*/
String pageName = "WXSample";
String bundleUrl = "http://dotwe.org/raw/dist/38e202c16bdfefbdb88a8754f975454c.bundle.wx";
wXSDKInstance.renderByUrl(pageName, bundleUrl, null, null, WXRenderStrategy.APPEND_ASYNC);
}
private void asyncLoadPages(final View view) {
/**
* 此处一定要判断WXSDKEngine是否已经成功初始化了,由于WXSDKEngine底层初始化的库非常多
* 导致整个的初始化非常的耗时,并且这个初始化是异步执行的,尤其是初始化JS引擎部分的代码(WXBridgeManager)。
* 因此有非常大的概率导致当第一次使用Week的API的时候,底层还没有完成初始化
* 导致出现错信息 "degradeToH5|createInstance fail|wx_create_instance_error isJSFrameworkInit==false reInitCount == 1"
* 这段耗时可以通过在程序启动的时候增加启动等待页面来人性化的忽略这部分耗时。
**/
if(!WXSDKEngine.isInitialized()) {
view.postDelayed(new Runnable() {
@Override
public void run() {
asyncLoadPages(view);
}
}, 1);
} else {
loadPages();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View view = findViewById(R.id.activity_main);
wXSDKInstance = new WXSDKInstance(this);
wXSDKInstance.registerRenderListener(this);
asyncLoadPages(view);
}
@Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
@Override
public void onViewCreated(WXSDKInstance instance, View view) {
setContentView(view);
}
@Override
public void onRenderSuccess(WXSDKInstance instance, int width, int height) {
Log.i(TAG, "onRenderSuccess");
}
@Override
public void onRefreshSuccess(WXSDKInstance instance, int width, int height) {
Log.i(TAG, "onRefreshSuccess");
}
@Override
public void onException(WXSDKInstance instance, String errCode, String msg) {
Log.e(TAG, "onException:" + msg);
}
@Override
protected void onResume() {
super.onResume();
if(wXSDKInstance!=null){
wXSDKInstance.onActivityResume();
}
}
@Override
protected void onPause() {
super.onPause();
if(wXSDKInstance!=null){
wXSDKInstance.onActivityPause();
}
}
@Override
protected void onStop() {
super.onStop();
if(wXSDKInstance!=null){
wXSDKInstance.onActivityStop();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if(wXSDKInstance!=null){
wXSDKInstance.onActivityDestroy();
}
}
}
需要注意的是`WXSDKEngine`是异步初始化的,导致在首次调用的时候,可能会因为没有正常初始化而出现异常,因此需要等待初始化完成。
具体的例子项目在这里下载 Weex
鉴于开源项目经常性找不到文件,因此记录下来 http://dotwe.org/raw/dist/38e202c16bdfefbdb88a8754f975454c.bundle.wx 这个文件里面的内容:
// { "framework": "Vue" }
/******/
(function(modules) { // webpackBootstrap
/******/ // The module cache
/******/
var installedModules = {};
/******/ // The require function
/******/
function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/
if (installedModules[moduleId])
/******/
return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/
var module = installedModules[moduleId] = {
/******/
exports: {},
/******/
id: moduleId,
/******/
loaded: false
/******/
};
/******/ // Execute the module function
/******/
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/
module.loaded = true;
/******/ // Return the exports of the module
/******/
return module.exports;
/******/
}
/******/ // expose the modules object (__webpack_modules__)
/******/
__webpack_require__.m = modules;
/******/ // expose the module cache
/******/
__webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/
__webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/
return __webpack_require__(0);
/******/
})
/************************************************************************/
/******/
([
/* 0 */
/***/
function(module, exports, __webpack_require__) {
'use strict';
var _e202c16bdfefbdb88a8754f975454c = __webpack_require__(1);
var _e202c16bdfefbdb88a8754f975454c2 = _interopRequireDefault(_e202c16bdfefbdb88a8754f975454c);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
_e202c16bdfefbdb88a8754f975454c2.default.el = '#root';
new Vue(_e202c16bdfefbdb88a8754f975454c2.default);
/***/
},
/* 1 */
/***/
function(module, exports, __webpack_require__) {
var __vue_exports__, __vue_options__
var __vue_styles__ = []
/* styles */
__vue_styles__.push(__webpack_require__(2))
/* script */
__vue_exports__ = __webpack_require__(3)
/* template */
var __vue_template__ = __webpack_require__(4)
__vue_options__ = __vue_exports__ = __vue_exports__ || {}
if (
typeof __vue_exports__.default === "object" ||
typeof __vue_exports__.default === "function"
) {
if (Object.keys(__vue_exports__).some(function(key) {
return key !== "default" && key !== "__esModule"
})) {
console.error("named exports are not supported in *.vue files.")
}
__vue_options__ = __vue_exports__ = __vue_exports__.default
}
if (typeof __vue_options__ === "function") {
__vue_options__ = __vue_options__.options
}
__vue_options__.__file = "/usr/src/app/raw/38e202c16bdfefbdb88a8754f975454c.vue"
__vue_options__.render = __vue_template__.render
__vue_options__.staticRenderFns = __vue_template__.staticRenderFns
__vue_options__._scopeId = "data-v-02e1e786"
__vue_options__.style = __vue_options__.style || {}
__vue_styles__.forEach(function(module) {
for (var name in module) {
__vue_options__.style[name] = module[name]
}
})
if (typeof __register_static_styles__ === "function") {
__register_static_styles__(__vue_options__._scopeId, __vue_styles__)
}
module.exports = __vue_exports__
/***/
},
/* 2 */
/***/
function(module, exports) {
module.exports = {
"text": {
"fontSize": 50
}
}
/***/
},
/* 3 */
/***/
function(module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
//
//
//
//
//
//
//
//
//
//
exports.default = {
data: function data() {
return {
text: 'Hello World.'
};
}
};
/***/
},
/* 4 */
/***/
function(module, exports) {
module.exports = {
render: function() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c('div', [_c('text', {
staticClass: ["text"]
}, [_vm._v(_vm._s(_vm.text))])])
},
staticRenderFns: []
}
module.exports.render._withStripped = true
/***/
}
/******/
]);
参考链接