android、ios都没有的混合JS和Java实现页面控制
背景
我们都知道前端开发中论开发效率,用类似小程序的开发效率要高于Android和IOS,因为小程序采用了H5的设计思想,采用Html5标签、CSS做页面布局和样式,JS控制逻辑和交互,H5的编写页面效率要远远高于Android和IOS,因此现代很多APP都采用了WebView方式的混合开发模式,通过H5实现页面,再通过JavaScript桥接方式实现调用到原生的方式。有没有不通过WebVIew的方式呢?经过我摸索,鸿蒙的交互设计真是强大,不仅能实现WebView的方式,还可以通过JSFA 调用 JAVAPA 拉起 JAVAFA,这样我们就可以轻松实现用JS Page方式实现UI,然后通过JS调用到Java中,在Java中再启动JS Page实现页面的流转。
实现的例子效果
现在我们就实现一个这样的例子:通过JS Page实现一个页面样式,然后点击页面中的一个按钮,再次启动一个 JS Page,在启动的JS Page中 在通过鸿蒙提供的router 更换页面。如下图:
实现步骤
(1)我们整体工程是在鸿蒙的Demo代码修改的。我们新建立工程,导入UI下面的JsAppDemo,如下图: (2) 先建立第2个JS page MainAbility2,最后会多出一个与default 并列的文件夹default2。在工程中的文件夹点击鼠标右键操作如图:
(3)建立第三个页面,在default2下面,点击鼠标右键建立一个新页面page3,操作如下图:
(4)建立MiddleAbility,主要用来实现JS调用到JAVA,这个文件是个服务Ability,操作如图:
,修改后 代码如下:
package ohos.samples.jsapplication; import ohos.aafwk.ability.Ability; import ohos.aafwk.content.Intent; import ohos.aafwk.content.Operation; import ohos.rpc.IRemoteObject; import ohos.hiviewdfx.HiLog; import ohos.hiviewdfx.HiLogLabel; import ohos.app.Context; import ohos.rpc.*; import java.io.OutputStream; import java.net.Socket; public class MiddleAbility extends Ability { private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo"); private static final int OPEN_NEWPAGE = 1001; private MiddleAbility.MideleRemote mideleRemote; @Override public void onStart(Intent intent) { HiLog.error(LABEL_LOG, "MiddleAbility::onStart"); super.onStart(intent); } @Override public void onBackground() { super.onBackground(); HiLog.info(LABEL_LOG, "MiddleAbility::onBackground"); } @Override public void onStop() { super.onStop(); HiLog.info(LABEL_LOG, "MiddleAbility::onStop"); } @Override public void onCommand(Intent intent, boolean restart, int startId) { } @Override public IRemoteObject onConnect(Intent intent) { Context context = getContext(); mideleRemote = new MiddleAbility.MideleRemote(context); return mideleRemote.asObject(); } @Override public void onDisconnect(Intent intent) { } class MideleRemote extends RemoteObject implements IRemoteBroker { private Context context; private Socket socket = null; private OutputStream os = null; public MideleRemote(Context context) { super("MideleRemote"); this.context = context; } @Override public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) throws RemoteException { switch (code) { case OPEN_NEWPAGE:{ System.out.println("开启页面2"); //主要代码 Intent intent = new Intent(); Operation operation = new Intent.OperationBuilder().withBundleName(getBundleName()) .withAbilityName(MainAbility2.class.getName()).build(); intent.setOperation(operation); startAbility(intent); //主要代码 break; } default: { reply.writeString("service not defined"); return false; } } return true; } @Override public IRemoteObject asObject() { return this; } } }
(5)修改Demo 中的js文件夹下的index.js 内容为:
/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ export const MiddleAbility = { openNewPage: async function(){ var actionData = {}; var action = {}; action.bundleName = 'ohos.samples.jsapplication'; action.abilityName = 'ohos.samples.jsapplication.MiddleAbility'; action.messageCode = 1001; action.data = actionData; action.abilityType = 0; action.syncOption = 0; var result = await FeatureAbility.callAbility(action); var ret = JSON.parse(result); if (ret.code == 0) { console.log(ret); } else { console.error(JSON.stringify(ret.code)); } } } export default { data: { cartText: '下一步', cartStyle: 'cart-text', isCartEmpty: true, descriptionFirstParagraph: 'This is the merchandise page that includes fresh fruit, meat, snacks, merchandise, and more. \nYou can pick anything you like and add it to your cart. \nYour order will arrive within 48 hours. We guarantee that we are organic and healthy. \n Feel free to ask our 24-hour online service to learn more about our platforms and products.', imageList: ['/common/item_000.png', '/common/item_001.png', '/common/item_002.png', '/common/item_003.png'], }, swipeToIndex(index) { this.$element('swiperImage').swipeTo({index: index}); }, addCart() { MiddleAbility.openNewPage(); }, getFocus() { if (this.isCartEmpty) { this.cartStyle = 'cart-text-focus'; } }, lostFocus() { if (this.isCartEmpty) { this.cartStyle = 'cart-text'; } }, }
(6) 修改default2下的index.hml,index.js 实现一个按钮点击跳转。index.js代码如下:
import router from '@system.router'; export default { data: { title: "" }, onInit() { this.title = this.$t('strings.world'); }, gotoNext:function (params) { router.push({ uri: 'pages/page3/page3' }); } }
经过以上步骤就完成了整个功能。
特别注意:在二个步骤中MainAbility2内容一定记得增加代码: setInstanceName("default2"); 如果没有这行代码就会出现都启动的是第一个页面内容。
总结
鸿蒙的功能设计确实很周到,这样可以充分调动前端开发人员的积极性,也为混合开发提供了强大的支持,这点很让人感到惊喜,这是我一个小小的探索。
源码下载地址:https://gitee.com/zhugqiang/NBjavaHarmony/tree/master/base/mix/harmony/JsApp

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java技术专题-JVM研究系列(40)Java各种类型对象占用内存情况分析(下)
前提回顾 建议大家从【Java技术专题-JVM研究系列(39)Java各种类型对象占用内存情况分析(上)】开始学习比较好,这样子会有一个承接和过度。根据前面的学习的内存占用计算规则,可以计算出一个对象在内存中的占用空间大小情况,下面举例分析下Java中的Enum, ArrayList及HashMap的内存占用情况,读者可以仿照分析计算过程来计算其他数据结构的内存占用情况。 注: 下面的分析计算基于HotSpot Jvm, JDK1.8, 64位机器,开启指针压缩。。 对象头 这里只关注其内存占用大小。在64位机器上,默认不开启指针压缩(-XX:-UseCompressedOops)的情况下,对象头占用12bytes,开启指针压缩(-XX:+UseCompressedOops)则占用16bytes。 实例数据: 对象引用(reference)类型在64位机器上,关闭指针压缩时占用8bytes, 开启时占用4bytes,一般指的是局部变量表或者操作数栈中的reference类型或者针对于成员变量情况下的地址引用(shallow size)。 注: 下面的分析计算基于HotSpot Jvm,...
- 下一篇
教你怎么开发一个基于java的语义waf
今天在看腾讯介绍自己jdk的文章,其中提到了腾讯的waf是java写的,所以到github上搜索了一下,发现了一个java开发的语义waf https://github.com/Kanatoko/libinjection-Java 这个项目的作者实在是太强了,使用的是libinjection的开发思路,所以我拿来研究了一下,产生了本文。 首先我写了一个有sql注入的接口如下,代码逻辑是name是sql拼接点,如果sql被库识别为sql注入,那么就直接拦截掉。 其中的我们要注意,因为本次是研究性质的,所以我会用sqlmap直接跑这个接口,对未发现的payload直接在Dirty SQLi found 中打印出来。 @RequestMapping("list2") public User getList2(String name) { //sql语句是 "select * from user where name='${name}'" if (name == null) { name = "dato"; } boolean isSQLi = com.client9.libinj...
相关文章
文章评论
共有0条评论来说两句吧...