Weex的迭代目前来说已经经过了很多版本,官方的文档已经过时,而且文档本身写的也很简陋,按官方文档很难把APP跑起来。经过多次趟坑后,决定把自己的经历写下来,给当前准备着手Weex开发的人一点参考:
npm install weex-toolkit -g
找一个目录作为Weex项目的工作空间(workspace),在命令行执行如下代码,创建weex项目:
weex create awesome-app
在命令行执行:
cd awesome-app
npm install
npm start
上面三个命令的意思分别是:进入awesome-app目录,安装依赖,启动。
所以后续需要运行weex工程,只需要在awesome-app目录下的命令行模式,运行npm start就能启动项目。
如图,我对代码做了一点修改
启动完成后会自动在浏览器中打开index界面,效果如下
至此,weex项目在web环境的搭建及运行就完成了。
下面开始Android开发所需的配置。
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
defaultConfig {
applicationId "cn.com.acoe.weexapp.app"
minSdkVersion 15
targetSdkVersion 19
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
buildToolsVersion '25.0.0'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
productFlavors {
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'com.alibaba:fastjson:1.1.46.android'
compile 'com.taobao.android:weex_sdk:0.18.0@aar'
compile 'com.squareup.okhttp:okhttp:2.3.0'
compile 'com.squareup.okhttp:okhttp-ws:2.3.0'
compile 'com.squareup.okio:okio:1.0.1'
compile 'com.github.bumptech.glide:glide:3.7.0'
}
因为示例中有图片的显示,所以除了官方文档给出的例子中依赖的几个包以外,我还引入了glide用于图片加载。okhttp是用来做网络请求的,所以我也引入了相关依赖。
package com.app.weexapp.util;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.taobao.weex.adapter.IWXImgLoaderAdapter;
import com.taobao.weex.common.WXImageStrategy;
import com.taobao.weex.dom.WXImageQuality;
public class ImageAdapter implements IWXImgLoaderAdapter {
@Override
public void setImage(String url, ImageView imageView, WXImageQuality wxImageQuality, WXImageStrategy wxImageStrategy) {
Glide.with(imageView.getContext()).load(url).into(imageView);
}
}
package com.app.weexapp.app;
import android.app.Application;
import android.util.Log;
import com.app.weexapp.util.ImageAdapter;
import com.taobao.weex.InitConfig;
import com.taobao.weex.WXSDKEngine;
/**
* Application
* Created by Acoe on 2018/4/4.
*/
public class WeexApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
InitConfig.Builder builder = new InitConfig.Builder();
builder.setImgAdapter(new ImageAdapter());
InitConfig config = builder.build();
WXSDKEngine.initialize(this, config);
Log.i("Application", "WXSDKEngine.isInitialized: " + WXSDKEngine.isInitialized());
}
}
package com.app.weexapp.ui;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import com.taobao.weex.IWXRenderListener;
import com.taobao.weex.WXSDKEngine;
import com.taobao.weex.WXSDKInstance;
import com.taobao.weex.common.WXRenderStrategy;
import com.taobao.weex.utils.WXFileUtils;
import cn.com.acoe.weexapp.app.R;
/**
* Created by Acoe on 2018/4/4.
*/
public class MainActivity extends AppCompatActivity {
private WXSDKInstance mWXSDKInstance;
private FrameLayout mContainer;
private Handler mHandler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContainer = (FrameLayout) findViewById(R.id.container);
mWXSDKInstance = new WXSDKInstance(this);
mWXSDKInstance.onActivityCreate();
mWXSDKInstance.registerRenderListener(new IWXRenderListener() {
@Override
public void onViewCreated(WXSDKInstance wxsdkInstance, View view) {
if (mContainer != null) {
mContainer.addView(view);
}
}
@Override
public void onRenderSuccess(WXSDKInstance wxsdkInstance, int i, int i1) {
}
@Override
public void onRefreshSuccess(WXSDKInstance wxsdkInstance, int i, int i1) {
}
@Override
public void onException(WXSDKInstance wxsdkInstance, String s, String s1) {
}
});
// 在渲染前先要保证WXSDKEngine已经完成了初始化
if (WXSDKEngine.isInitialized()) {
startRender();
} else {
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0) {
Log.i("Main", "WXSDKEngine.isInitialized: " + WXSDKEngine.isInitialized());
if (WXSDKEngine.isInitialized()) {
startRender();
} else {
msg = mHandler.obtainMessage(0);
mHandler.sendMessageDelayed(msg, 100);
}
}
}
};
Message msg = mHandler.obtainMessage(0);
mHandler.sendMessageDelayed(msg, 100);
}
Log.i("Main", "onCreate over");
}
/**
* 开始执行渲染
*/
private void startRender() {
mWXSDKInstance.render("Main", WXFileUtils.loadAsset("app.js", this),
null, null, WXRenderStrategy.APPEND_ASYNC);
}
@Override
protected void onResume() {
super.onResume();
if (mWXSDKInstance != null) {
mWXSDKInstance.onActivityResume();
}
}
@Override
protected void onPause() {
super.onPause();
if(mWXSDKInstance != null) {
mWXSDKInstance.onActivityPause();
}
}
@Override
protected void onStop() {
super.onStop();
if(mWXSDKInstance != null) {
mWXSDKInstance.onActivityStop();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if(mWXSDKInstance != null) {
mWXSDKInstance.onActivityDestroy();
}
}
}
布局文件的代码,activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">FrameLayout>
LinearLayout>
如果有看过其他的weex介绍的文章,或者看过官网的文章,可以发现我的Activity代码有一点不一样的地方,就是在WXSDKInstance.render()执行weex界面渲染之前判断了WXSDKEngine是否有初始化完成。
因为我在没有加这个判断及相应的处理之前,weex在浏览器里显示的那个界面一直渲染不出来,但是在debug一步一步找原因的过程中,发现在渲染之前断点多停留一会儿,界面最终就渲染出来了。
而且日志中也出现多条JsFramework没有初始化的提示,于是就怀疑是在MainActivity进行界面渲染的时候WXSDKEngine应该还没有初始化成功,导致渲染失败。
最终加上了确保WXSDKEngine初始化成功后再进行渲染,解决了问题。
这个坑网上真是找不到一丁点资料,weex的相关文章还是太少,有深入了解的人也应该还是不多。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.com.acoe.weexapp.app">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name="com.app.weexapp.app.WeexApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name="com.app.weexapp.ui.MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
intent-filter>
activity>
application>
manifest>
至此从搭建环境到运行,整个流程就结束了。有什么不祥尽的地方敬请留言我会进行补充的。
虽然Weex官方提出的“一次编写,处处运行”可以说是做到了,但是原生的工作量确实还是不少。其实如果阿里把Weex专门运营成一个API产品,前景应该还是非常好的,类似于国内DCloud、ACloud做的那样,底层封装好,开发者只关注于前端怎么实现,与底层的交互全是API厂商封装好的那样。但是阿里似乎不太可能有这样子的做法,但是给混合开发开创了一种高体验的途径,这点相信会给很多人带来启示。反正就目前而言,个人觉得不是一个很好的混合开发解决方案,仍然还有很多路要走。
github地址:https://github.com/Acoee/WeexApp.git
参考文档
[1]: 官方手册 http://weex.apache.org/cn/guide/