Android混合开发的入门和方案

2023-11-01

前言

其实之前一直都很抵制hybrid开发,因为作为一个Android开发程序员,总是觉得原生的更好(其实是不想丢饭碗),但是一个闲着没事干,就写了一个demo搭了个webview,然后把html文件放到asset下面,一加载惊呆宝宝了,简直跟原生的没有区别啊,体验跟原生基本一样(andrid 5.0以后webview的速度比之前的版本有很大的提升),至此我就走上了学习混合开发的道路.

前期准备 WebView

其实我相信很多跟我一样刚入门混合开发的人,对于应该要学习哪部分知识都会感到迷惑,在这里我先谈谈我的经验:

  1. html基础,不用说很厉害,但是至少你要知道整个html的体系还有css,div等控件的使用,还有对html节点的一些基本操作
  2. javaScript基础,这里说的基础就是语法之类的,js这一部分其实挺重要的,跟上面一样,但是js你懂得越多,少走的坑也就真的越少,切身体会啊!!!
  3. 对一些常见的前段框架的运用,比如jquery,sui-mobile,第三点倒不是很重要
  4. webview的原理,这一点挺重要的,因为它涉及到webview中的js怎么去与android的native交互的原理,懂得原理你可以在混合开发中更加”自由地”做出你想要的东西

把网页搬到自己的app上面

假如我们的第一个需求是:把一个网页搬到自己的app上面。那此时,我们只需要下面这段代码就行

public class BolgActivity extends AppCompatActivity {

    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bolg);
        webView = (WebView) findViewById(R.id.webview);
        //这段代码的作用是让webview不要使用系统自带浏览器
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url){
                return false;
            }
        });
        webView.loadUrl("http://www.baidu.com");
    }
}

运行结果:
图片名称
在一般情况下,我们的做法都是把html文件放在app的asset目录下,然后通过下面的代码来加载html文件,这样大大提高了加载速度

mWebView.loadUrl("file:///android_asset/index.html");

native提供帮助

很明显这不能满足我们的需求,这样你的应用和浏览器又有什么区别,那现在我们提高要求。假如现在我们有一个新的需求:
要求网页弹出一个加载框(要求不是网页的加载框,而是android系统原生的加载框)
在完成这个需求之前,就必须先讲讲webview中的页面怎么去和android原生交互了.我们可以先把webview想象成一个容器,那么html页面就是运行在这个容器上面的.
那么我们的webview想要去调用html页面里的js就通过下面这段代码

webView.loadUrl("javascript: log()");

那么js中要调用android里面的代码就是通过webview注入一个对象,然后让js调用,下面我用伪代码表示一下:

{
    //假设这里是activity里面
    webView.addJavascriptInterface(new JsInterface(), "interface");
    class JsInterface{
        void showToast(String msg){
            Toast.make(MainActivity.this, toast, Toast.LENGTH_SHORT).show();
        }   
    }
}
-------------------------------------------------------
{
    //假设这里是在一段JavaScript函数里面
    interface.showToast("I'm js");
}

上面讲的是第一种js和native交互的方式,其实我说的很直白,如果看不懂可以看看下面这篇博文:
js与webview的交互(并不是很喜欢这种转载的,但由于原创的那篇打不开,将就一下吧)

进阶 JsBridge

ps:上面我们讲了js与native交互的一种方案,但在实际运用中我发现并不是很好用,js与native的调用一多,会显得代码非常混乱,当然后面也有个方案能解决,甚至比我接下来要讲的方案还要好,这里先讲下我现在在使用的方案。
相信我的这篇blog是你查阅了大量资料以后才无意中看到的,那么你肯定是知道JsBridge了。先看看代码

{
    //这是在native中的代码,mWebView为JsBridge封装过的webview
    mWebView.callHandler("myInit", "我是数据", new CallBackFunction() {
            @Override
            public void onCallBack(String data) {

            }
        });
}
-----------------------------------------------------------------------------------------------------
{
    //这是在Js中的代码,bridge是native注入在js中的对象
    bridge.registerHandler("functionInJs", function(data, responseCallback) {
                document.getElementById("content").innerHTML = ("data from Java: = " + data);
                var responseData = "Javascript Says  我要你的地址!";
                responseCallback(responseData);
            });
}

上面这段代码什么意思呢?就是在js中通过bridge注册一个函数,然后在native中通过封装好的webview.callHandler函数来调用js中已经注册好的函数,那么反过来Js想调用native的函数,也是同样的道理,只要在native中注册好函数,在js中通过bridge.callHandler来调用就行了。
这样给我们的开发提供了极大的方便,而且避免了很多代码混乱的情况,那么它的基本原理是什么呢?下面我还是用最简单地语言来讲一讲。

  • 在我们的webview中,可以设置自定义的WebChromeClient,这个东西就是加载在webview中的html中有弹窗事件的时候会回调的
  • WebChromeClient里面有很多种回调,其中有一个回调方法onJsPrompt,这个方法就是我们的突入点(其他方法也都可以,但是可能会干扰到原来的逻辑,这个比较少用,所以我们用这个)

语言是不是很简单暴力?如果你还看不懂,看看下面的实例:

{
    //假设这里是在js里面
    var uri = "hybrid://objectName:sid/methodName?params";
    var value = "xxxxxxx";
    window.prompt(uri, value);
}
--------------------------------------------------------------
{
    //这是在activity里面
    public class InjectedChromeClient extends WebChromeClient {
            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                //这里传进来的参数就是从js的window.prompt(uri, value)传过来的参数
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }
    }
}

JsBridge的工作原理就是这样,那么现在看来好像对我们没什么用呀?下面我举个实际应用的例子说一下,就拿上面那个例子来说:要求网页弹出一个加载框(要求不是网页的加载框,而是android系统原生的加载框)
(先不要讲太复杂的代码,从上面JsBridge的知识我们已经知道了js里面能传递数据给webview)

{
    //假设这个方法是js中负责发送数据给webview的
    function postToNative(data){..省略..}
    var data = 
    {
        "tagName":"showLoadingDialog",
        "pars":{
            "content":"正在加载中",
            "title":"请等待",
            //这个callback就是当加载框被取消的时候native回调js中的函数
            "callback":"onLoadingCancel"
        }   
    };
    postToNative(data);
}

{
    //假设这个方法实在native中接收webview中的js发过来的数据
    void receiveJsData(String data){
        //上面js的函数可以看出,js向我们发送了一段json数据
        //所以我们只需解析这段数据,便可知道js需要native做什么事
    }
}

总结

对比

觉得上面讲的都是废话?
其实网上关于hybrid开发的文章我敢说我基本都看过了,国外的文章也有看了看,在实际开发中,我自己也写了很多demo,下面是我总结的关于一些JsBridge的优缺点:
优点

  1. 相比传统的方式方便很多,代码更加简洁
  2. 其实第一点已经完爆一切了,写不出第二点了哈哈

缺点
1. 调试困难,不知是否是博主基础太差,过程中有许多意料不到的错(当然是关于js的),不过到后面基本都能解决了
2. 如果要做到一个页面可以兼容所有web页面,那需要注册的函数太多了,因为每个页面需要的功能都不一样
3. 生命周期有点难掌控,假如你在JsBridge未初始化之前就调用,那么会导致JsBridge初始化失败(之前这个坑陷了好久后面才发现的)

实际应用

在实际开发中,我的方法是通过json来灵活地定义每个动作,也就是利用json数据,来告诉native我需要做什么动作。通过这种方式,一个app甚至只要一个activity就能解决所有的页面,此时有人要问了,那我每个页面的ui就都一样了吗?比如说toolbar,alertDialog。
然而并不是这样的,通过我上面将的知识点,可以在js初始化的时候,定义一段json数据,用户初始化ui,例如下面的:

var data =
{
    "title":"话题列表",
    "right":{
        "icon":"R.mipmap.ic_launcher",
        "description":"描述",
        "callback":"onRightBtnClick"
    }
};

然后在native中解析这段数据,来达到初始化ui的效果,这种方式我也已经运用在我的项目中。
相信你看了这边文章,你已经基本知道了webview在实际开发中的应用和各种方案,如果觉得文章有哪些地方写的不好,请留言说明。

ps:代码下次贴出,在写个几个基类供参考,写得还不是很完善,需要的也提出来把!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android混合开发的入门和方案 的相关文章

随机推荐

  • flutter强制横屏竖屏设置

    void main 强制横屏 SystemChrome setPreferredOrientations DeviceOrientation landscapeLeft DeviceOrientation landscapeRight ru
  • Latex 约等于符号

    approx
  • 深入理解Python 中的特殊常量None

    False 不同 它不表示 0 也不表示空字符串 而表示没有值 也就是空值 None 有自己的数据类型 我们可以在 IDLE 中使用 type 函数查看它的类型 执行代码如下 gt gt gt type None
  • LangChain 中文入门教程

    文章目录 LangChain 中文入门教程 一 介绍 1 1 背景 1 2 基础功能 二 必知概念 2 1 Loader 加载器 2 2 Document 文档 2 3 Text Spltters 文本分割 2 4 Vectorstores
  • 语音中的 Transformer一文打尽!

    写在前面 自 2017 年 Transformer 技术出现以来 便在 NLP CV 语音 生物 化学等领域引起了诸多进展 知源月旦团队期望通过 Transformer X 梳理清 Transformer 技术的发展脉络 以及其在各领域中的
  • BigQueue:The Architecture and Design of a Publish & Subscribe Messaging System Tailored for Big Data

    The Architecture and Design of a Publish Subscribe Messaging System Tailored for Big Data Collecting and Analytics MAR 2
  • stm32USART使用(库函数)

    1 定义GPIO端口 串口USART 中断NVIC初始化结构体 2 打开相关外设时钟 串口1的时钟和引脚都在APB2总线上所以可以直接 操作 如下 3 给GPIO结构体成员赋值 设置引脚功能 此处用的是USART1 Tx是PA9 Rx是PA
  • 【MarkDown】CSDN Markdown之时间轴图timeline详解

    文章目录 时间轴图 一个关于时间轴图的例子 语法 分组 长 时间段 或 事件文本 换行 时间段 和 事件文本 样式 自定义颜色方案 主题 基础主题 森林主题 黑色主题 默认主题 中性主题 与库或网站集成 时间轴图 时间轴图 现在这是一个实验
  • 电子元器件篇---电感

    目录 简介 电感主要参数 2 1 标称感值 2 2 允许偏差 2 3 额定电流 2 4 品质因数 2 5 分布电容 2 6 封装规格 电感种类 电感用途 4 1 LC滤波电路 4 2延迟作用 4 3陷波作用 4 4 LC振荡电路 简介 电感
  • centos7 sublime text 3打开.html或者.asp乱码解决办法

    下载codecs33库 https github com seanliang Codecs33 tree linux x64 或者在sublime text 3里直接下插件 codecs33
  • C++ 之 浮点数的大小比较

    摘要 本文首先 将 介绍 浮点数 的 存储结构 以及 int 操作 含义 其次 介绍 常规 浮点数比较 方法 最后 本文 将采用 int 转换为 整型 数据 直接比较 转换为的 整形数据 的 大小 1 浮点数 的 存储结构 十进制 1 35
  • systemd服务管理---systemctl命令列出所有服务

    1 列出系统所有服务 systemctl list units all type service
  • win10不能将文件拖到另外一个程序中去的解决办法

    author headsen chen date 2019 07 25 14 48 32 notice 个人原创 新建一个 aa txt的文本文档 Windows Registry Editor Version 5 00 HKEY LOCA
  • 【Plupload插件】基础使用教程

    前言 Plupload是一款由著名的web编辑器TinyMCE团队开发的上传组件 简单易用且功能强大 特点 拥有多种上传方式 HTML5 flash silverlight以及传统的 Plupload会自动侦测当前的环境 选择最合适的上传方
  • Idea插件开发(一)——插件的分类及基础认识

    Idea插件开发 一 插件的分类及基础认识 Idea插件开发 二 插件的创建打包及发布 Idea插件开发 三 插件JSL的完整开发过程 本篇文章基于IntelliJ Platform SDK DevGuide抽取主要部分内容 官方详细开发文
  • U-boot移植,添加正点原子板子报错:致命错误:configs/.h:没有那个文件或目录

    在创建完成mx6ull alientek emmc deconfig include configs mx6ull alientek emmc h文件以及板级文件夹board freescale mx6ull alientek emmc及文
  • 读书笔记:《把时间当作朋友》

    开头 金句 1 今天的错误将必然导致明天的尴尬 为了避免将来的尴尬必须在今天采取正确的行动 2 我常常这样告诉自己 你并不孤独 当我遇到麻烦的时候 我会这么对自己说 告诉自己遇到这种麻烦的人并不只我一个 所以只要想办法寻找解决方案就好 弄不
  • SAP FI/SD的集成-VKOA科目确定

    前言 一 组成部分 二 使用步骤 1 VKOA确定收入科目 1 1定义物料科目分配组 1 2定义客户科目分配组 2 V 08定价过程 3 库存成本Inventory的自动记账科目配置 OBYC 总结 前言 财务和销售集成的点 也是各种SAP
  • SpringCloud微服务架构的学习理解一

    一 什么是springcloud springCloud是集合了其他的技术 多达21种的技术 集成了为微服务工作的各个组件 二 什么是微服务架构 微服务架构是由马丁 福勒提出的 将单一的应用程序划分为多个模块的进行服务设计的一种架构风格 其
  • Android混合开发的入门和方案

    前言 其实之前一直都很抵制hybrid开发 因为作为一个Android开发程序员 总是觉得原生的更好 其实是不想丢饭碗 但是一个闲着没事干 就写了一个demo搭了个webview 然后把html文件放到asset下面 一加载惊呆宝宝了 简直