1. 云栖社区>
  2. 博客列表>
  3. 正文

Weex总结之Android Weex工程搭建趟坑

启舰君 2016-08-03 10:19:58 浏览4446 评论1

阿里技术协会

摘要: >目前虾米也打算接入Weex,内网上看似很多的基础教程,但根据讲解一步步做下来却一直无法实现效果。仔细看资料,才了解究竟是为什么,把自己的心得记录下来方便后来者。 今天要完成的效果就是使用Android工程来渲染下面的效果: ![blog1](http://img3.tbcdn.cn/L1/461/1/09c2f48df4a244bc707b8bfdfa0a545c334b00ab)

目前虾米也打算接入Weex,内网上看似很多的基础教程,但根据讲解一步步做下来却一直无法实现效果。仔细看资料,才了解究竟是为什么,把自己的心得记录下来方便后来者。

今天要完成的效果就是使用Android工程来渲染下面的效果:
blog1

一、基本释义

首先解释几个概念,方便大家有个整体了解

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界面,就说明安装成功了
blog2
下面就是使用weex-toolkit转换we文件了

cd XXXX 
weex tech_list.we 

(tech_list.we文件在底部源码工程根目录下)
上面总共两句话,首先,将当前工作路径切换到we文件所在的目录,如果不切,则需要指定we文件所在的绝对路径。
然后直接使用weex命令转换即可
在输入命令以后,首先会直接打开一个网页显示这个we文件的渲染效果:
blog3
然后在tech_list.we文件所在的文件夹下,会产生一个文件夹weex_temp,这个文件夹是就浏览器中所显示的内容的源文件,其中有一个跟tech_list.we所对应的tech_list.js文件,它就是转换后的js文件,我们在Android工程中所使用的就是它!
blog4
在拿到tech_list.js以后,我们就开始搭Android工程了;

有关weex命令的更多用法,请参考《Transform Code into Js Bundle》

二、搭建Android Weex工程

这篇文章不基于源码构建,本篇文章的宗旨是教大家先跑起来……在跑起来以后再引入源码构建就好办了。

1、新建项目

(1)、新建gradle项目,Minimum SDK不得低于14;(低于14,Weex不支持)
blog5
(2)、配置gradle
在工程根目录下build.gradle文件中,加入阿里仓库,以便引入远程weex包:

allprojects {
    repositories {
        jcenter()
        maven{
            url "http://mvnrepo.alibaba-inc.com/mvn/repository"
        }
    }
}

文件位置如图:
blog6
(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上。
文件位置如下:
blog7

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文件添加到其中
blog8

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

用云栖社区APP,舒服~

【云栖快讯】《阿里持续集成与持续交付最佳实践》系列直播来啦!解析痛点与挑战、研究案例,摆脱手工作坊式研发,赶紧报名!  详情请点击

网友评论

1F
爱淘儿

文章末尾的源码地址不能访问(貌似是内网的)。能换一个外网可以访问的代码仓库吗?

阿里云机器学习是基于阿里云分布式计算引擎的一款机器学习算法平台。用户通过拖拉拽的方式可视化的操作组件来进行试验,...

基于深度学习技术及阿里巴巴多年的海量数据支撑, 提供多样化的内容识别服务,能有效帮助用户降低违规风险。其产品包括...

凝聚阿里巴巴多年来在无线业务安全防御的成功经验和技术成果,并面向开发者和企业提供安全扫描、应用加固、安全组件、数...

为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效率,降低 IT 成本...
阿里云免费套餐上线!

阿里云免费套餐上线!