webview 交互的两种方式

1 jsbridge promise 封装


/*
 * @Author: zhangyu
 * @Email: zhangdulin@outlook.com
 * @Date: 2021-06-11 11:00:48
 * @LastEditors: zhangyu
 * @LastEditTime: 2021-06-16 18:07:04
 * @Description: 
 */

//JS注册事件监听
var initflag  = false

function connectWebViewJavascriptBridge(callback) {
 if (window.WebViewJavascriptBridge) {
     callback(WebViewJavascriptBridge)
 } else {
     document.addEventListener(
         'WebViewJavascriptBridgeReady'
         , function() {
             callback(WebViewJavascriptBridge)
         },
         false
     );
 }
}

//注册回调函数,第一次连接时调用 初始化函数
// connectWebViewJavascriptBridge(function(bridge) {
//   //初始化
//  bridge.init(function(message, responseCallback) {
//    initflag = true
//      var data = {
//          'Javascript Responds': 'Wee!'
//      };
//      // alert("jasdashjd");
//      responseCallback(data);
//  });
// })

 /**
  * @description: jsbridge callHandler
  * @param {*} callHandlerData 
  * @param {*} name n请求的方法
  * @param {*} data 请求时传的参数
  * @return {*} function
  */
 export function callHandler (callHandlerData={name:'', data:{}}) {
   let _resolve
   let _reject
   // 生成promise对象,保留resolve,reject
   const readyPromise = new Promise((resolve, reject) => {
     _resolve = resolve
     _reject = reject
   })
   connectWebViewJavascriptBridge(function(bridge) {
    //初始化
    if (!initflag) { 
     bridge.init(function(message, responseCallback) {
     initflag = true
       var data = {
           'Javascript Responds': 'Wee!'
       };
       responseCallback(data);
      });
      try {
        bridge.callHandler(callHandlerData.name, callHandlerData.data, (response) => {
          // 调用成功,使用保留的resolve改变返回的promise状态
          _resolve(response)
         })
       } catch (e) {
         // 调用成功,使用保留的reject改变返回的promise状态
         _reject(e)
        }
   } else {
     try {
       bridge.callHandler(callHandlerData.name, callHandlerData.data, (response) => {
         // 调用成功,使用保留的resolve改变返回的promise状态
         _resolve(response)
       })
     } catch (e) {
       // 调用成功,使用保留的reject改变返回的promise状态
       _reject(e)
     }
   }
  })
  
   return readyPromise
 }


 /*
 * @Author: zhangyu
 * @Email: zhangdulin@outlook.com
 * @Date: 2021-06-11 11:00:48
 * @LastEditors: zhangyu
 * @LastEditTime: 2021-06-11 14:05:50
 * @Description: 
 */
// 注册方法获取WebViewJavascriptBridge对象
function setupWebViewJavascriptBridge(callback) {
  if (window.WebViewJavascriptBridge) {
    return callback(window.WebViewJavascriptBridge)
  }
  if (window.WVJBCallbacks) {
    return window.WVJBCallbacks.push(callback)
  }
  // 兼容安卓
  document.addEventListener(
    'WebViewJavascriptBridgeReady',
    () => callback(window.WebViewJavascriptBridge),
    false
  )
  // 兼容ios
  window.WVJBCallbacks = [callback]
  var WVJBIframe = document.createElement('iframe')
  WVJBIframe.style.display = 'none'
  WVJBIframe.src = 'https://__bridge_loaded__'
  document.documentElement.appendChild(WVJBIframe)
  setTimeout(function() {
    document.documentElement.removeChild(WVJBIframe)
  }, 0)
}
//  获取WebViewJavascriptBridge对象
function getBirdge() {
  return new Promise(resolve => {
    if (window.WebViewJavascriptBridge) {
      return resolve(window.WebViewJavascriptBridge)
    }
    setupWebViewJavascriptBridge(bridge => {
      // 初始化
      bridge.init(function(message, responseCallback) {
        var data = {
            'Javascript Responds': 'Wee!'
        };
        responseCallback(data);
      });

      resolve(bridge)
    })
  })
}

// 重写之后的birdge
/**
* @description: jsbridge callHandler
* @param {*} callHandlerData 
* @param {*} name n请求的方法
* @param {*} data 请求时传的参数
* @return {*} function
*/
export default {
  ctx: null, // WebViewJavascriptBridge
  callHandler(callHandlerData={name:'', data:{}}) {
    return new Promise(async resolve => {
      if (!this.ctx) {
        this.ctx = await getBirdge()
      }
      this.ctx.callHandler(callHandlerData.name, callHandlerData.data, res => resolve(res))
    })
  },
  registerHandler(jsHandlerName) {
    // 重写事件注册方法
    this.ctx.registerHandler(jsHandlerName, (data, callback) => {
      if (callback) {
        callback(
          `返回一个字符串,告诉ObjC:我已收到数据${JSON.stringify(data)}`
        )
      }
    })
  }
}

2 dsbirdge 性能更好 写法优雅 原生ios 安卓统一规范

npm 引入
npm i dsbridge

测试例子

<!--
 * @Author: zhangyu
 * @Email: zhangdulin@outlook.com
 * @Date: 2021-06-18 10:41:17
 * @LastEditors: zhangyu
 * @LastEditTime: 2021-06-18 10:41:17
 * @Description: 
-->
<!DOCTYPE html>
<html>
<head lang="zh-cmn-Hans">
    <meta charset="UTF-8">
    <title>DSBridge Test</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta name="viewport" content="width=device-width,initial-scale=0.5,user-scalable=no"/>
    <!--require dsbridge init js-->
    <script src="https://cdn.jsdelivr.net/npm/dsbridge/dist/dsbridge.js"> </script>
</head>
<style>
    .btn {
        text-align: center;
        background: #eee;
        color: #000;
        padding: 20px;
        margin: 30px;
        font-size: 24px;
        border-radius: 4px;
        box-shadow: 4px 2px 10px #999;
    }

    .btn:active {
        opacity: .7;
        box-shadow: 4px 2px 10px #555;
    }



</style>
<body>
<div class="btn" onclick="callSyn()">Synchronous call</div>
<div class="btn" onclick="callAsyn()">Asynchronous call</div>
<div class="btn" onclick="callSynSwift()">Syn call (swift)</div>
<div class="btn" onclick="callAsynSwift()">Async call(swift)</div>
<div class="btn" onclick="callNoArgSyn()">Sync call without argument</div>
<div class="btn" onclick="callNoArgAsyn()">Async call without argument</div>
<div class="btn" onclick="echoSyn()">echo.syn</div>
<div class="btn" onclick="echoAsyn()">echo.asyn</div>
<div class="btn" onclick="callAsyn_()">Stress test,2K times consecutive asynchronous API calls</div>
<div class="btn" onclick="callNever()">Never call because without @JavascriptInterface
    annotation<br/>( This test is
    just for Android ,should be ignored in IOS )
</div>
<div class="btn" onclick="callProgress()">call progress <span id='progress'></span></div>
<div class="btn" onclick="hasNativeMethod('xx')">hasNativeMethod("xx")</div>
<div class="btn" onclick="hasNativeMethod('testSyn')">hasNativeMethod("testSyn")</div>

<script>

    function callSyn() {
      alert(dsBridge.call("testSyn", "Hello"))
    }

    function callAsyn() {
        dsBridge.call("testAsyn","hello", function (v) {
            alert(v)
        })
    }

function callSynSwift() {
    alert(dsBridge.call("swift.testSyn", "hello"))
}

function callAsynSwift() {
    dsBridge.call("swift.testAsyn","hello", function (v) {
                  alert(v)
                  })
}

    function callAsyn_() {
        for (var i = 0; i < 2000; i++) {
            dsBridge.call("testAsyn",  "js+" + i, function (v) {
                if (v == "js+1999 [ asyn call]") {
                    alert("All tasks completed!")
                }
            })
        }
    }

    function callNoArgSyn() {
        alert(dsBridge.call("testNoArgSyn"));
    }

    function callNoArgAsyn() {
        dsBridge.call("testNoArgAsyn", function (v) {
            alert(v)
        });
    }

    function callNever() {
        alert(dsBridge.call("testNever", {msg: "testSyn"}))
    }

    function echoSyn() {
        // call function with namespace
        var ret=dsBridge.call("echo.syn",{msg:" I am echoSyn call", tag:1});
        alert(JSON.stringify(ret))
    }

    function echoAsyn() {
        // call function with namespace
        dsBridge.call("echo.asyn",{msg:" I am echoAsyn call",tag:2},function (ret) {
            alert(JSON.stringify(ret));
        })
    }

    function callProgress() {
        dsBridge.call("callProgress", function (value) {
            if(value==0) value="";
            document.getElementById("progress").innerText = value
        })
    }

    function hasNativeMethod(name) {
        alert(dsBridge.hasNativeMethod(name))
    }


    dsBridge.register('addValue', function (r, l) {
        return r + l;
    })

    dsBridge.registerAsyn('append', function (arg1, arg2, arg3, responseCallback) {
        responseCallback(arg1 + " " + arg2 + " " + arg3);
    })

    dsBridge.registerAsyn('startTimer', function (responseCallback) {
        var t = 0;
        var timer = setInterval(function () {
            if (t == 5) {
                responseCallback(t)
                clearInterval(timer)
            } else {
                // if the 2nd argument is false,  the java callback handler will be not removed!
                responseCallback(t++, false)
            }
        }, 1000)

    })

    // namespace test for syn functions
    dsBridge.register("syn", {
        tag: "syn",
        addValue:function (r,l) {
            return r+l;
        },
        getInfo: function () {
            return {tag: this.tag, value:8}
        }
    })

    // namespace test for asyn functions
    dsBridge.registerAsyn("asyn", {
        tag: "asyn",
        addValue:function (r,l, responseCallback) {
            responseCallback(r+l);
        },
        getInfo: function (responseCallback) {
            responseCallback({tag: this.tag, value:8})
        }
    })

</script>
</body>
</html>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值