• Android weex的集成和开发


    最近为了项目需要(实际上是为了年底KPI),领导要求用3天时间,学习并使用weex开发一个页面,说实话,压力山大。在这之前压根儿就没听说过啊,一脸懵逼

    无奈之余只能Google了,惊喜的发现weex的官网上面是什么都有啊,环境搭建、weex集成开发、js教程等等还有好多,双手奉上官网地址:http://weex.apache.org/cn/

    既然官网讲的这么全面,我就只说一下我的操作流程;

    1、weex环境搭建

    首先下载安装node.js,node.js是weex编译、打包用的基础工具,javascript和node.js关系,类似于java与jvm,nodejs去官方网站下载最新稳定版6.xx就可以

    安装好了之后,用以下命令检查是否安装成功

    node -v
    npm -v

    出现上图就说明node.js安装成功了

    npm是nodejs的包管理工具,相当于android中的gradle或者iOS中的cocoapods,但是npm在国内访问速度较慢,建议大家安装cnpm,是淘宝的一个npm国内镜像

    安装完cnpm后执行cnpm install -g weex-toolkit安装weex-toolkit

    $ npm install -g cnpm --registry=https://registry.npm.taobao.org
    $ cnpm install -g weex-toolkit
    

     

    命令行敲weex,出现上图就说明weex-toolkit安装成功了。

    至此weex的安装就告一段落了,官网上的环境搭建到这里之后还有几步,不过我都没有用上,这里先记一下,后续需要用到了再补充!!!!!!

    2、集成到 Android

    接下来就是将weex项目集成到Android项目中去,这块真是没有什么好讲的,这块就和集成第三方sdk一毛一样的

    直接上官网的集成方式:http://weex.apache.org/cn/guide/integrate-to-your-app.html

    2-1、个人对weex开发的理解

    说一下我对在Android中集成weex的理解吧,可能理解的很浅显,不喜勿喷!

    weex旨在“一次撰写,多端使用”,意思是,用weex写的页面,不论是Android还是iOS甚至web端都可以使用,这样的话就可以极大的降低开发成本,

    weex其实就是写的一个类似于h5的页面(js编写),写完之后将vue文件编译、部署到Nginx服务器上(Nginx服务器后面会讲到),这时候在你的Nginx服务器下的html文件夹内会生成一个.js的文件,这个.js文件就是你要嵌入到Android项目内的文件,如果一个项目内有很多个weex页面,就需要编译部署很多个vue文件,也就是说会在html这个文件夹下生成很多个.js文件,然后你可能会问,那我们要怎么管理和维护这么多个.js文件呢?这就需要我们将这些个.js压缩成一个zip包,把这个压缩后的zip包个后台,后台会生成一个json文件,将这个.json放在Nginx服务器的html文件夹内,我们需要做的就只是管理和维护这个.json文件就可以了,最后在你的Android项目内,访问这个Nginx服务器(服务器的地址就是你电脑的ip地址),获取到服务器上的weex页面(其实这也能做到预加载的作用)然后进行各种处理和操作;

    生成的.json文件就是这么个东西,在后文要讲的获取页面,完全靠这里面的url,非常的重要;

    贴一些util代码吧:

        //在mainActivity或者启动页获取weex相关json文件
        WeexUtils.getPages();
    
        public static void getPages() {
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String url = http://ip地址/后台生成的.json文件;
                    okhttp3.Request request = new okhttp3.Request.Builder()
                            .url(url)
                            .build();
                    try {
                        okhttp3.Response response = AlbatrossApplication.getInstance().getClient().newCall(request).execute();
                        String data = response.body().string();
          //okhttp请求.json数据,最后将请求到的数据通过sharedprefer存储到本地 SharedPreferences pages
    = AlbatrossApplication.getInstance().getSharedPreferences("pages", MODE_PRIVATE); pages.edit().putString("pages", data).commit(); downloadBundle(); } catch (IOException e) { e.printStackTrace(); } } }).start(); }

    下载weex bundle:

        /**
         * 下载weex bundle
         */
        public static void downloadBundle() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        SharedPreferences pages = AlbatrossApplication.getInstance().getSharedPreferences("pages", MODE_PRIVATE);
                        String pagesData = pages.getString("pages", "");
                        com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(pagesData);
                        String url = jsonObject.getJSONObject("zip").getString("url");
                        String path = AlbatrossApplication.getInstance().getCacheDir() + File.separator + "weex";
                        if (!new File(path).exists()) {
                            new File(path).mkdirs();
                        }
                        File downloadedFile = new File(path, "js_bundle.zip");
                        String localMd5 = WeexUtils.calculateMD5(downloadedFile);
                        if (jsonObject.getJSONObject("zip").getString("md5").equals(localMd5)) {
                            //本地zip和服务器zip一致,return
                            return;
                        }
    
                        okhttp3.Request request = new okhttp3.Request.Builder()
                                .url(url)
                                .build();
    
                        okhttp3.Response response = AlbatrossApplication.getInstance().getClient().newCall(request).execute();
                        BufferedSink sink = Okio.buffer(Okio.sink(downloadedFile));
                        sink.writeAll(response.body().source());
                        sink.close();
                        Log.e("bobo", downloadedFile.length() + "   " + downloadedFile.getAbsolutePath());
                        WeexUtils.unzip(downloadedFile, new File(path));
                        Log.e("bobo 当前目录文件数", new File(path).listFiles().length + "");
    
    //                    downloadPatch();//下载patch
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

    以上的操作就可以获取到weex页面了,获取到了之后就可以开始操作了,这里我就简单的举一个点击跳转的例子好了,上代码

            View view = findviewById(R.id.tv_consist);
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    WXSDKInstance mWXSDKInstance = new WXSDKInstance(getActivity());
                    Intent intent = new Intent(getActivity(), WeexActivity.class);
                    intent.putExtra("WX_URL",  "/html文件夹下的js文件.js");
                    mWXSDKInstance.getContext().startActivity(intent);
                }
            });

    跳转到WeexActivity后,在WeexActivity进行的处理就是将前文存储在本地的数据解析,根据解析后的数据获取到指定.js文件的路径,最后加载这个路径的页面,这块挺乱的,我说的只是一个大概方向,具体的还要看实际情况;

    public class WeexActivity extends BaseMainActivity implements View.OnClickListener, IWXRenderListener {
        private String TEST_URL = "http://172.16.36.232/dist/jump.js";
        private WXSDKInstance mWXSDKInstance;
        private FrameLayout mContainer;
        private TextView mTv_title;
        private HashMap<String, String> mLocalBundleBean;
        private TextView mTv_right;
        private boolean isFinish = true;
        private View mTv_left;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    //        KYApplication.getInstance().addActivity(this);
            setContentView(R.layout.activity_weex);
            initView();
    
            WXSDKEngine.setActivityNavBarSetter(new NavigatorAdapter());
            mContainer = (FrameLayout) findViewById(R.id.container);
            mWXSDKInstance = new WXSDKInstance(this);
            mWXSDKInstance.registerRenderListener(this);
            /**
             * pageName:自定义,一个标示符号。
             * url:远程bundle JS的下载地址
             * options:初始化时传入WEEX的参数,比如 bundle JS地址
             * flag:渲染策略。WXRenderStrategy.APPEND_ASYNC:异步策略先返回外层View,其他View渲染完成后调用onRenderSuccess。WXRenderStrategy.APPEND_ONCE 所有控件渲染完后后一次性返回。
             */
            Map<String, Object> options = new HashMap<>();
            String wx_url = getIntent().getStringExtra("WX_URL");
            String title = getIntent().getStringExtra("title");
    //        mTv_title.setText(title);
            TEST_URL = wx_url.substring(wx_url.lastIndexOf("/")+1);
            options.put(WXSDKInstance.BUNDLE_URL, TEST_URL);
    
            //获取集合,维护文件md5值以及文件对应路径
            //从json文件里,取出md5对应的文件,有则加载文件,无则加载url
            SharedPreferences pages = getSharedPreferences("pages", MODE_PRIVATE);
            String pageData = pages.getString("pages", "");
    
            JSONObject jsonObject = JSON.parseObject(pageData);
            JSONArray jsonArray = jsonObject.getJSONArray("pages");
    
            HashMap<String, PageBean> pageMap = new HashMap<>();//存储服务器最新页面信息
            for (int i = 0; i < jsonArray.size(); i++) {
                PageBean pageBean = JSON.parseObject(jsonArray.getString(i), PageBean.class);
                pageMap.put(pageBean.getPage(), pageBean);
            }
    
            mLocalBundleBean = new HashMap<>();
            try {
                long time = System.currentTimeMillis();
                getAllFiles(new File(Constant.WEEX_URL));//本地zip包解压文件md5
                Log.e("bobo", "计算md5总耗时" + (System.currentTimeMillis() - time));
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            PageBean pageBean = pageMap.get(TEST_URL);//获取login.js对应的md5、url
            if(pageBean==null){
                Toast.makeText(this,"页面不存在", Toast.LENGTH_SHORT).show();
                return;
            }
            String localUrl = mLocalBundleBean.get(pageBean.getMd5());
            TEST_URL=pageBean.getUrl();
            if (null != localUrl) {
                mWXSDKInstance.render(TEST_URL, WXFileUtils.loadFileOrAsset(localUrl, this), null, null, WXRenderStrategy.APPEND_ASYNC);
                Log.e("bobo","从本地加载");
            } else {
                mWXSDKInstance.renderByUrl(TEST_URL, TEST_URL, options, null, WXRenderStrategy.APPEND_ONCE);
                Log.e("bobo","从网络加载");
            }
    //        mWXSDKInstance.renderByUrl("WXSample", TEST_URL, options, null, WXRenderStrategy.APPEND_ONCE);
        }
    
        public void initView() {
            mTv_left = findViewById(R.id.tv_left);
            mTv_title = (TextView) findViewById(R.id.tv_title);
            mTv_right = (TextView) findViewById(R.id.tv_right);
            mTv_left.setOnClickListener(this);
            mTv_title.setOnClickListener(this);
            mTv_right.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View view) {
            if (view.getId() == R.id.tv_left) {
                if(isFinish){
                    super.onBackPressed();
                }else {
                    mWXSDKInstance.fireGlobalEventCallback("left_click", null);
                }
            } else if (view.getId() == R.id.tv_title) {
    //            Toast.makeText(this, "标题点击了", Toast.LENGTH_SHORT).show();
            } else if (view.getId() == R.id.tv_right) {
                mWXSDKInstance.fireGlobalEventCallback("clickrightitem", null);
            }
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            if (mWXSDKInstance != null) {
                mWXSDKInstance.onActivityStart();
            }
        }
    
        @Override
        protected void onResume() {
            super.onResume();
    
            WXStorageModule wxStorageModule = new WXStorageModule();
            wxStorageModule.setItem("currentPage", WXUtils.getNameFromUrl(TEST_URL),null);
    
            if (mWXSDKInstance != null) {
                mWXSDKInstance.onActivityResume();
    
                //发送页面出现广播
                Map<String, Object> params = new HashMap<>();
                params.put("page", WXUtils.getNameFromUrl(TEST_URL));
                mWXSDKInstance.fireGlobalEventCallback("appear", params);
            }
        }
    
        @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();
    //        KYApplication.getInstance().deleteActivity(this);
            if (mWXSDKInstance != null) {
                mWXSDKInstance.onActivityDestroy();
            }
        }
    
        @Override
        public void onViewCreated(WXSDKInstance instance, View view) {
            if (view.getParent() != null) {
                ((ViewGroup) view.getParent()).removeView(view);
            }
            mContainer.addView(view);
    
            //发送页面出现广播
            Map<String, Object> params = new HashMap<>();
            params.put("page", WXUtils.getNameFromUrl(TEST_URL));
            mWXSDKInstance.fireGlobalEventCallback("appear", params);
        }
    
        @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) {
    
        }
    
        private class NavigatorAdapter implements IActivityNavBarSetter {
    
            @Override
            public boolean push(String param) {
                return false;
            }
    
            @Override
            public boolean pop(String param) {
                return false;
            }
    
            @Override
            public boolean setNavBarRightItem(String param) {
                String title = JSON.parseObject(param).getString("title");
    
                if(!TextUtils.isEmpty(title) && ("添加报价".equals(title) || "返回首页".equals(title))){
                    mTv_right.setTextColor(getResources().getColor(R.color.color_5E8BF8));
                }
                mTv_right.setText(title);
                return false;
            }
    
            @Override
            public boolean clearNavBarRightItem(String param) {
                return false;
            }
    
            @Override
            public boolean setNavBarLeftItem(String param) {
                return false;
            }
    
            @Override
            public boolean clearNavBarLeftItem(String param) {
                return false;
            }
    
            @Override
            public boolean setNavBarMoreItem(String param) {
                return false;
            }
    
            @Override
            public boolean clearNavBarMoreItem(String param) {
                return false;
            }
    
            @Override
            public boolean setNavBarTitle(String param) {
                String title = JSON.parseObject(param).getString("title");
                mTv_title.setText(title);
                return false;
            }
        }
    
        public void getAllFiles(File file) throws Exception {
            File[] files = file.listFiles();
    //        long time = System.currentTimeMillis();
            for (int i = 0; i < files.length; i++) {
                if (files[i].isDirectory()) {
                    getAllFiles(files[i]);
                } else {
                    Log.e("bobo", "name" + files[i].getName() + "  md5" + WeexUtils.calculateMD5(files[i]));
                    mLocalBundleBean.put(WeexUtils.calculateMD5(files[i]), files[i].getAbsolutePath());
                }
            }
        }
    
        /**
         * @return get mWXSDKInstance
         */
        public WXSDKInstance getWXSDKInstance() {
            return mWXSDKInstance;
        }
    
        @Override
        public void onBackPressed() {
            if(isFinish){
                super.onBackPressed();
            }else {
                mWXSDKInstance.fireGlobalEventCallback("back_click", null);
            }
        }
    
        /**
         * Sets the isFinish  设置是否直接返回上个页面
         * You can use getFinish() to get the value of isFinish
         */
        public void setFinish(boolean finish) {
            isFinish = finish;
        }
    
        public void hideBackButton(){
            mTv_left.setVisibility(View.GONE);
        }
    }
    View Code

    3、Nginx服务器

    终于到最后一步了,Nginx服务器下载地址:http://nginx.org/en/download.html

    我是下载的稳定版

    下载完之后解压到文件夹下,双击nginx.exe启动服务,打开conf这个文件夹,打开nginx.conf这个文件,修改location下的root

    3-1、编译、部署.vue文件

    哦。对了,大家应该都是到用webstorm写vue页面吧??哈哈哈哈

    (1)首次创建项目或者是首次导入项目的时候,需要在控制台执行:cnpm install,这个就类似于Android studio中的sync now。

    我们需要通过这个命令将package.json中的所有依赖下载下来;

    (2)同样的,控制台执行:weex compile src/vue文件名 D: ginx ginx-1.12.2html

     意思是将制定的vue文件编译到nginx服务器下的指定文件夹内,这时候就会生成一个前文所说到的.js文件。

    终于全都结束了,这是我今天一天的调研学习的成果,可能有一些地方理解的有偏差或者不对的地方,非常欢迎大家批评指正

    如果有任何疑问,欢迎留言~~~~

                                                        2017/12/6 21:05 晚安各位

  • 相关阅读:
    Python 3.6安装yaml时报"AttributeError: module 'pip' has no attribute 'main'"和“Non-zero exit code”错误
    Python 3.6版本中实现 HTMLTestRunner输出时”fp=file(filename,'wb')“报错
    LoadRunner录制脚本时没有响应——无法启动浏览器问题总结
    python中print不换行
    python中for循环的三种遍历方式
    python enumerate用法
    Python中添加中文注释报错SyntaxError: Non-UTF-8 code starting with 'xc1'
    pycharm 2017最新激活码
    设计模式之禅2之六大原则
    hibernate错误整理
  • 原文地址:https://www.cnblogs.com/upwgh/p/7994854.html
Copyright © 2020-2023  润新知