当前位置: 代码网 > it编程>编程语言>Javascript > 鸿蒙HarmonyOS应用开发初体验(1)

鸿蒙HarmonyOS应用开发初体验(1)

2024年08月06日 Javascript 我要评论
| MainAbility | MainActivity | 入口页。鸿蒙中将四大组件的概念统一成 || MainAbilityListSlice | XXXFragment | 类似Fragment,UI的基本组成单元 || Component | View | 类相当于View,后文介绍 || config.json | AndroidManifest.xml | 鸿蒙使用json替代xml进行Manifest配置,配置项目差不多 || resources/base/… | res/… | 包括

| mainability | mainactivity | 入口页。鸿蒙中将四大组件的概念统一成ability |
| mainabilitylistslice | xxxfragment | slice类似fragment,ui的基本组成单元 |
| component | view | component类相当于view,后文介绍 |
| config.json | androidmanifest.xml | 鸿蒙使用json替代xml进行manifest配置,配置项目差不多 |
| resources/base/… | res/… | 包括layout文件在内的各种资源文件依旧使用xml |
| resources/rawfile/ | assets/ | rawfile存储任意格式原始资源,相当于assets |
| build.gradle | build.gradle | 编译脚本,两者一样 |
| build/outpus/…/*.hap | build/outputs/…/*.apk | 鸿蒙的产物是hap(harmony application package)
解压后里面有一个同名的.apk文件,
这后续是因为鸿蒙需要同时支持apk安装的兼容方案 |

ability

ability是应用所具备能力的抽象,harmony支持应用以ability为单位进行部署。一个应用由一个或多个fa(feature ability)或pa(particle ability)组成。fa有ui界面,提供与用户交互的能力;而pa无ui界面,提供后台运行任务的能力以及统一的数据访问抽象

  • fa支持page ability:
  • page ability用于提供与用户交互的能力。一个page可以由一个或多个abilityslice构成,abilityslice之间可以进行页面导航

image.png

  • pa支持service ability和data ability:
  • service ability:用于提供后台运行任务的能力。
  • data ability:用于对外部提供统一的数据访问抽象。

可以感觉到,各种ability可以对照android的四大组件来理解

harmonyandroid
page ability (fa)activity
service ability (pa)service
data ability(pa)contentprovider
abilityslicefragment

代码一览

mainability

以预置的news feature ability为例子,这是一个拥有两个slice的page ability,通过router注册两个slice

public class mainability extends ability {

@override
public void onstart(intent intent) {
super.onstart(intent);
super.setmainroute(mainabilitylistslice.class.getname()); //添加路由:listslice
addactionroute(“action.detail”, mainabilitydetailslice.class.getname());//detailslice


}
}

以下是在模拟器中运行两个slice的页面效果

mainabilitylistslicemainabilitydetailslice
image.pngimage.png
mainabilitylistslice

主要看一下列表的显示逻辑

public class mainabilitylistslice extends abilityslice {

@override
public void onstart(intent intent) {
super.onstart(intent);
super.setuicontent(resourcetable.layout_news_list_layout);
initview();
initdata(); //加载数据
initlistener();
newslistcontainer.setitemprovider(newslistadapter); //adatper设置到view
newslistadapter.notifydatachanged(); //刷新数据
}

private void initlistener() {
newslistcontainer.setitemclickedlistener((listcontainer, component, i, l) -> {
//路由跳转"action.detail"
logutil.info(tag, “onitemclicked is called”);
intent intent = new intent();
operation operation = new intent.operationbuilder()
.withbundlename(getbundlename())
.withabilityname(“com.example.myapplication.mainability”)
.withaction(“action.detail”)
.build();
intent.setoperation(operation);
startability(intent);
});
}

private void initdata() {

totalnewsdatas = new arraylist<>();
newsdatas = new arraylist<>();
initnewsdata();//填充newsdatas
newslistadapter = new newslistadapter(newsdatas, this);//设置到adapter
}


}

类似listview的用法,通过adatper加载数据; setitemclickedlistener中通过路由跳转mainabilitydetailslice。

layout_news_list_layout布局文件定义如下,listcontainer即listview,是comopnent的一个子类,component就是harmonyos中的view

<?xml version="1.0" encoding="utf-8"?>

看一下adapter的实现, 继承自baseitemprovider

/**

  • news list adapter
    */
    public class newslistadapter extends baseitemprovider {
    private list newsinfolist;
    private context context;

public newslistadapter(list listbasicinfo, context context) {
this.newsinfolist = listbasicinfo;
this.context = context;
}

@override
public int getcount() {
return newsinfolist == null ? 0 : newsinfolist.size();
}

@override
public object getitem(int position) {
return optional.of(this.newsinfolist.get(position));
}

@override
public long getitemid(int position) {
return position;
}

@override
public component getcomponent(int position, component componentp, componentcontainer componentcontainer) {
viewholder viewholder = null;
component component = componentp;
if (component == null) {
component = layoutscatter.getinstance(context).parse(resourcetable.layout_item_news_layout, null, false);
viewholder = new viewholder();
component componenttitle = component.findcomponentbyid(resourcetable.id_item_news_title);
component componentimage = component.findcomponentbyid(resourcetable.id_item_news_image);
if (componenttitle instanceof text) {
viewholder.title = (text) componenttitle;
}
if (componentimage instanceof image) {
viewholder.image = (image) componentimage;
}
component.settag(viewholder);
} else {
if (component.gettag() instanceof viewholder) {
viewholder = (viewholder) component.gettag();
}
}
if (null != viewholder) {
viewholder.title.settext(newsinfolist.get(position).gettitle());
viewholder.image.setscalemode(image.scalemode.stretch);
}
return component;
}

/**

  • viewholder which has title and image
    */
    private static class viewholder {
    text title;
    image image;
    }
    }

基本上就是标准的listadatper,把view替换成component而已。

关于模拟器

代码完成后可以再模拟器中运行。关于模拟器有几点想说的:

  1. harmony的模拟器启动非常快,无需下载镜像,因为这个模拟器并非本地运行,而只是一个远端设备的vnc,因此必须在线使用,而且不够流畅时有丢帧现象。虽然真机调试效果更好,但不是人人都买得起p40的

  2. 模拟器嵌入到ide窗口显示(像preview窗口一样),非独立窗口,这会带来一个问题,当同时打开多个ide时,模拟器可能会显示在另一个ide中(就像logcat跑偏一样)。

  3. 想使用模拟器必须进过开发者认证,官方推荐使用银行卡认证。模拟器远端链接的是一台真实设备,难道是为未来租用设备要计费??image.png记得以前看过一篇文章,如果是来自国外地区的注册账号可以免认证使用模拟器,但是懒得折腾了

3. 开发js应用


除了java,鸿蒙还支持基于js开发应用,借助前端技术完善其跨平台能力。

鸿蒙为js工程提供了多种常用ui组件,但是没有采用当下主流的react、vue那样js组件,仍然是基于css3/html5/js这种传统方式进行开发。js工程结构如下

image.png

目录说明
common可选,用于存放公共资源文件,如媒体资源、自定义组件和js文档等
i18n可选,用于存放多语言的json文件
pages/index/index.hmlhml文件定义了页面的布局结构,使用到的组件,以及这些组件的层级关系
pages/index/index.csscss文件定义了页面的样式与布局,包含样式选择器和各种样式属性等
pages/index/index.jsjs文件描述了页面的行为逻辑,此文件里定义了页面里所用到的所有的逻辑关系,比如数据、事件等
resources可选,用于存放资源配置文件,比如:全局样式、多分辨率加载等配置文件
app.js全局的javascript逻辑文件和应用的生命周期管理。

4. 跨设备迁移


通过前面的介绍,可能感觉和android大同小异,但是harmonyos最牛逼之处是多端协作能力,例如可以将page在同一用户的不同设备间迁移,实现无缝切换。

以page从设备a迁移到设备b为例,迁移动作主要步骤如下:

  • 设备a上的page请求迁移。
  • harmonyos回调设备a上page的保存数据方法,用于保存迁移必须的数据。
  • harmonyos在设备b上启动同一个page,并回调其恢复数据方法。

通过调用continueability()请求迁移。如下,获取设备列表,配对成功后请求迁移

doconnectimg.setclickedlistener(
clickedview -> {
// 通过flag_get_online_device标记获得在线设备列表
list deviceinfolist = devicemanager.getdevicelist(deviceinfo.flag_get_online_device);
if (deviceinfolist.size() < 1) {
widgethelper.showtips(this, “无在网设备”);
} else {
deviceselectdialog dialog = new deviceselectdialog(this);
// 点击后迁移到指定设备
dialog.setlistener(
deviceinfo -> {
logutil.debug(tag, deviceinfo.getdevicename());
logutil.info(tag, “continue button click”);
try {
// 开始任务迁移
continueability();
logutil.info(tag, “continue button click end”);
} catch (illegalstateexception | unsupportedoperationexception e) {
widgethelper.showtips(this, resourcetable.string_tips_mail_continue_failed);
}
dialog.hide();
});
dialog.show();
}
});

page迁移涉及到数据传递,此时需要借助iabilitycontinuation进行通信。

跨设备通信 iabilitycontinuation

跨设备迁移的page需要实现iabilitycontinuation接口。

public class mainability extends ability implements iabilitycontinuation {

@override
public void oncompletecontinuation(int code) {}

@override
public boolean onrestoredata(intentparams params) {
return true;
}

@override
public boolean onsavedata(intentparams params) {
return true;
}

@override
public boolean onstartcontinuation() {
return true;
}

设计模式学习笔记

设计模式系列学习视频

《android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,即可获取!
rams) {
return true;
}

@override
public boolean onstartcontinuation() {
return true;
}

设计模式学习笔记

[外链图片转存中…(img-nkmpww0g-1715435723744)]

设计模式系列学习视频

[外链图片转存中…(img-cqs6ippk-1715435723745)]

《android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,即可获取!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com