目前虾米也打算接入Weex,内网上看似很多的基础教程,但根据讲解一步步做下来却一直无法实现效果。仔细看资料,才了解究竟是为什么,把自己的心得记录下来方便后来者。
今天要完成的效果就是使用Android工程来渲染下面的效果:
一、基本释义
首先解释几个概念,方便大家有个整体了解
1、DSL与we文件
在有些文章中会提到 Weex DSL或者DSL,那么这个DSL究竟是个什么鬼呢?
DSL的全称是领域特定语言,是针对特定问题领域的编程语言,而非通用语言。所以Weex DSL也就是指针对Weex 所缩写的一套语言。
而利用Weex DSL语言所写的程序,保存时的格式就是我们常见的.we后缀格式。
2、we文件与js文件
在Android代码中,无法直接加载.we文件的,但是可以加载.js文件的,所以我们需要把.we文件转换成.js文件,Weex给我们提供了一个工具weex-toolkit
首先,我们需要利用nmp在命令行安装它:
npm install -g weex-toolkit
在安装完以后,在命令行,只输入weex,如果出现下面Help界面,就说明安装成功了
下面就是使用weex-toolkit转换we文件了
cd XXXX
weex tech_list.we
(tech_list.we文件在底部源码工程根目录下)
上面总共两句话,首先,将当前工作路径切换到we文件所在的目录,如果不切,则需要指定we文件所在的绝对路径。
然后直接使用weex命令转换即可
在输入命令以后,首先会直接打开一个网页显示这个we文件的渲染效果:
然后在tech_list.we文件所在的文件夹下,会产生一个文件夹weex_temp,这个文件夹是就浏览器中所显示的内容的源文件,其中有一个跟tech_list.we所对应的tech_list.js文件,它就是转换后的js文件,我们在Android工程中所使用的就是它!
在拿到tech_list.js以后,我们就开始搭Android工程了;
有关weex命令的更多用法,请参考《Transform Code into Js Bundle》
二、搭建Android Weex工程
这篇文章不基于源码构建,本篇文章的宗旨是教大家先跑起来……在跑起来以后再引入源码构建就好办了。
1、新建项目
(1)、新建gradle项目,Minimum SDK不得低于14;(低于14,Weex不支持)
(2)、配置gradle
在工程根目录下build.gradle文件中,加入阿里仓库,以便引入远程weex包:
allprojects {
repositories {
jcenter()
maven{
url "http://mvnrepo.alibaba-inc.com/mvn/repository"
}
}
}
文件位置如图:
(3)、添加依赖
在app项目中的build.gradle文件中,添加项目依赖:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.taobao.android:weex_sdk:0.5.1' //添加SDK library依赖
compile 'com.android.support:recyclerview-v7:23.3.0'
compile 'com.alibaba:fastjson:1.1.45'
compile 'com.squareup.picasso:picasso:2.5.2'
}
其中除了最后一个picasso依赖是我自己加进去的以外,另外四个都是必须添加的。因为weex_sdk底层是依赖他们的,只是以provided形式引入其中的,所以我们上层必须complie上。
文件位置如下:
2、初始化
在添加依赖以后,我们就开始正式写代码了,首先是需要将Weex在应用程序onCreate时候初始化:
public class WeexApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
InitConfig.Builder builder = new InitConfig.Builder();
builder.setImgAdapter(new ImageAdapter());
// builder.setHttpAdapter(new DefaultWXHttpAdapter());
InitConfig config = builder.build();
WXSDKEngine.initialize(this,config);
}
}
weex的初始化主要是靠WXSDKEngine.initialize(this,config)
函数,该函数声明如下:
public static void initialize(Application application, InitConfig config)
关键在于第二个参数InitConfig config,它是由InitConfig.Builder()构造得来的,InitConfig.Builder()中可以让我们通过setImgAdapter来设置自定义的图片加载器,通过setHttpAdapter来自定义网络请求方式。但我们有一点必须强调的是:weex的优势在于渲染,所以除了渲染以外的事情,都需要我们自己来做。也就是说加载图片和网络请求都需要我们自己来写方法实现;如果我们没有实现,那么当有图片加载请求和网络请求时,就不会执行任何实际代码,也就不会有任何效果!这也就是在初始化的时候,需要通过builder.setImgAdapter和builder.setHttpAdapter来设置自定义适配器的原因!庆幸的是,weex为我们实现了默认的网络请求适配器DefaultWXHttpAdapter,当发现我们在网络请求时,并没有定义网络适配器就会使用默认的DefaultWXHttpAdapter来请求网络。但可惜的是,weex并没有为我们实现默认的图片适配器,所以我们在初始化的时候必须实现自己的图片加载适配器,并通过 builder.setImgAdapter设置进去。如果我们没有写,那当需要加载图片的时候,就相当于执行了空方法,原来需要显示图片的地方就不会有任何显示!
然后我们来看看我们自定义的ImageAdapter是如何实现的:
public class ImageAdapter implements IWXImgLoaderAdapter {
public ImageAdapter() {
}
@Override
public void setImage(final String url, final ImageView view,WXImageQuality quality, WXImageStrategy strategy) {
WXSDKManager.getInstance().postOnUiThread(new Runnable() {
@Override
public void run() {
if (TextUtils.isEmpty(url)) {
view.setImageBitmap(null);
return;
}
String temp = url;
if (url.startsWith("//")) {
temp = "http:" + url;
}
if (view.getLayoutParams().width <= 0 || view.getLayoutParams().height <= 0) {
return;
}
Picasso.with(WXEnvironment.getApplication())
.load(temp)
.into(view);
}
},0);
}
}
在写适配器时,我们必须实现IWXImgLoaderAdapter接口,当需要加载图片时,就会通过IWXImgLoaderAdapter的setImage方法传过来,在setImage的参数中,第一个参数final String url表示网络图片地址,第二个参数,表示当前需要显示图片的View
我们这里只需要从网上加载图片,并将结果设置给View就可以了。哪种方法随意……我这里使用的Picasso,这也是为什么在依赖中添加Picasso依赖的原因
3、AndroidManifest配置
我们在自定义了Application以后,一样要记得在AndroidManifest.xml中引入:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.harvic.tryWeex.qijianweex.app">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:name=".WeexApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".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>
注意添加网络权限和引入WeexApplication
4、添加JS文件
首先将我们在文章开头的tech_list.js文件添加到工程中,在java文件夹的同级目录中,添加一个assets文件夹,将tech_list.js文件添加到其中
5、MyActivity加载JS文件
首先,需要说明一点,weex只负责渲染,渲染出来以后会返回一个结果View给我们,我们把它放到哪里就是我们自己来决定了,所以,首先,我们需要提供一个container来盛装返回的View,所以MyActivity的布局如下:(main.xml)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
这里的FrameLayout,就是用来盛装结果用的Container;
然后MyActivity中的代码如下:
public class MainActivity extends AppCompatActivity {
private FrameLayout mContainer;
protected WXSDKInstance mWeexInstance;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContainer = (FrameLayout)findViewById(R.id.container);
mWeexInstance = new WXSDKInstance(this);
mWeexInstance.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) {
}
});
mWeexInstance.render("qijianWeex", WXFileUtils.loadFileContent("tech_list.js", this), null, null, -1, -1, WXRenderStrategy.APPEND_ASYNC);
}
}
最关键是下面的三行代码:
mWeexInstance = new WXSDKInstance(this);
mWeexInstance.registerRenderListener(new IWXRenderListener() {
@Override
public void onViewCreated(WXSDKInstance wxsdkInstance, View view) {
if (mContainer != null){
mContainer.addView(view);
}
}
…………
});
mWeexInstance.render("qijianWeex", WXFileUtils.loadFileContent("tech_list.js", this), null, null, -1, -1, WXRenderStrategy.APPEND_ASYNC);
首先,我们使用mWeexInstance.render()函数就可以渲染本地的js文件了,在渲染成功以后,我们需要监听渲染结果,并将它添加到我们的container中,所以我们利用mWeexInstance.registerRenderListener()来监听渲染状态。当完成以后,会在onViewCreated中将渲染成功的View对象返回,我们只需要将它加载到container中显示出来即可。
如果我们需要加载远程js文件,可以使用:
mInstance.renderByUrl("pageName", "远程js地址", null, null, -1, -1, WXRenderStrategy.APPEND_ASYNC);
OK啦,到这里本篇就结束了,运行出来的效果就如开篇所示;
源码地址:http://gitlab.alibaba-inc.com/WeexDemo/qijianWeex