开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情
前言
事情是这样的,就是在和前端的哥对接的时候,就是Android和web的通信,Android调用Web的一个方法,传了参数过去,json的字符串参数,然后老哥来找我说,我怎么把对象传给他,让我改成传字符串给他。
也就是这串代码
webView.loadUrl("javascript:" + function + "(" + params + ")");
我当时瞬间懵B了,跨端通讯能传个吉尔对象,我说是你那边转的吧,跨端通信怎么可能传得了对象,跨端通信都是传基础数据类型和字符串。但是他不信,一口咬定就是我传对象。没办法,总不能都干瞪眼吧,我就是详细查看怎么回事,其实这种只要有点常识的都知道是内部自己转,然后我找到如果想让内部不转的话,就这样写
webView.loadUrl("javascript:" + function + "('" + params + "')");
这件事之后,我觉得就很无奈,因为这明明就是一个常识,他却不信,关键我还说服不了他,没有强有力的证据。
原来我也不懂跨端通信
然后我就去思考,如何说服他。
首先,跨端通信,肯定传不了对象,这个是毋庸置疑的,对象只是你这个端定义的东西,并不是所有端都适用,更准确来说,应该是基础数据类型也不能直接传,内部是会做转换的。举个简单的例子,就拿NDK来说,虽然在调用时能传对象,但是native层接收对象的结构体是jobject,是做了转换的。
那这个转换是怎么做的呢?这个转换的逻辑应该是不同的端要写不同的转换逻辑,我举一个不是很恰当的例子,拿Serializable来说,序列化之后,其实数据里面不光是数据信息,还包含类信息这些,然后是有一定的格式的。这边也一样,比如我在android端传个对象给其它端,其它端拿到子解码之后,根据这个格式拿到有用的数据,再其它端创建一个该端的对象结构,把数据填进去。
但是想着想着我又想到了一个点,那其它端是怎么调用java的方法的呢?想到这我突然就感到很懵B了。
有的人就说了,前端调Android就是直接拦截或者addJavascriptInterface方法啊,这我不懂?就拿addJavascriptInterface来说,那它里面呢,它底层封装的呢?最终怎么在js中调用到java的?难道你能在在js中写javaObject.function(xxx)?
包括做游戏的有用C#和java通信,那是怎么实现的?其实这些问题都属于同一个问题,要想通这个问题,最好还是拿C++和java的通信来说,它们怎么通信的,jni,那jni里面做了什么,具体的我也不清楚,但好像它有JVM的对象,所以我觉得这事和JVM有关。
但仔细一想,好像确实是那么一回事,你想想,怎么调用java对象的方法的,javaObject.function(xxx),在java中是这样调用的,那javaObject这个对象存在哪里?存在堆中。堆在哪里?堆在虚拟机中。所以要拿到对象,只能通过JVM从它的堆中找,所以一切的跨端通信应该都是要通过JVM ,而且JVM是底层的代码,所以这个过程是要经过底层。
那返回来想,前端是在怎么调用到的,我想,前端页面是运行在webview上,webview的内核是WebKit,WebKit是android系统有提供的Native C/C++ Libraries ,所以它是能调用到JVM的。所以我认为webview是通过WebKit,WebKit去调用JVM,拿到具体的对象,然后再调用具体的方法。反过来,java调用js的方法,应该靠的是解释器。
但我还是不懂跨端通信,因为我不懂JVM中具体的操作和其中一些详细流程,但我感觉大体的流程应该是这样的。
最后附送一下,如果在网上找不到你想要的答案怎么办