HarmonyOS实战—亮眼的原子化服务体验

简介: HarmonyOS实战—亮眼的原子化服务体验

2021年6月2日晚20:00,华为HarmonyOS 2及华为全场景新品发布会如期召开。发布会上,重磅发布了万众瞩目的HarmonyOS 2正式版,HarmonyOS正式到来!


在最新的HarmonyOS 2.0中,"服务卡片"成为一个新的亮点。


其实不止是服务卡片,更是这种原子化服务的理念,简洁,高效,开放,带来的想象力和创新,开启了信息化时代的新的一页,相信以后基于鸿蒙的创新场景,会如雨后春笋般的不断涌现。


什么是服务卡片?


服务卡片(以下简称“卡片”)是一种界面展示形式,将重要信息或操作直接放置到卡片中,用户通过直接操作卡片就可以达到应用的使用体验,这样做大大减少了应用的使用层级性。

卡片常用于嵌入到其他应用中作为其界面的一部分显示(也可以使用原子化服务将应用保存到服务中心中,这种方式不需要安装应用),并支持拉起页面,发送消息等基础的交互功能。


有一下特色:


  1. 全新的Harmonyos桌面简洁有序,上滑App生成服务卡片,在桌面即可呈现更丰富的信息。


  1. 卡片内容实时更新,只需一管即可获取所需信息,省去了打开App的时间。


  1. 卡片可大可小、可藏可显,还能够个性化定制,让每个桌面独一无二。


  1. 卡片也是原子化服务的载体,在服务中心可以轻松获取、随时分享,无需下载、安装,一步到位获取各种服务。


什么是原子化服务?


原子是构成应用的不可再分解的基本服务单元,鸿蒙原子化服务强调的是轻量化服务、免安装应用,也便于为其他应用共享,轻量化的服务可以随意组合,且可有意突出特色化的服务,可为用户提供一个或多个便捷的用户程序形态。试想一个庞大的app有很多服务,都揉合在一个应用中不但操作繁琐,且没有重点,不能有效的吸引用户,里面庞大的百分之七八十的功能可能用户都不关注。且庞大的体系也不利于传播,复用和快速迭代。在平台微服务化,移动端小程序化大行其道火热的今天,华为把类似的概念引入鸿蒙系统,生成一个新的连接场景,提供了更新的想象空间。关于原子化服务的更多内容,参见:HarmonyOS Developer:什么是原子化服务


来看下几个火热的例子:


距离HarmonyOS 2.0发布不到一个月时间,6月25日,国泰君安上线了HarmonyOS原子化服务,一次推出“君弘Lite”、“开户”两个原子化服务卡片。同在6月25日,兴业证券官宣也发布鸿蒙生态服务卡片“优理宝”。


招商银行、中国银行等金融机构此前也官宣上线鸿蒙原子化服务,积极布局开放银行场景新生态。


鸿蒙原子化服务具备免安装、轻量化的特性,其载体为卡片,在服务中心可以轻松获取、随时分享,无需下载、安装。基于 HarmonyOS 2,南航向用户推出“机票预订”和“航班动态”两个原子化服务。其最大特点是用户无需下载“南方航空”App,即可获得与 App 相同的使用体验。



招行银行试着将财富管理的服务从App外延至鸿蒙系统,以App热门栏位“财富直击”为抓手,形成一个原子化服务向客户推荐,当用户看见心仪产品时,即可完成购买。


还有更多的企业不断的在跟进中,大有争先恐后之势。第一次感受到有证券部门比技术部还着急的,因为大凡沾点鸿蒙概念的边,那啥都长飞了。在数字化转型的关键时期,单是在银行业就将迎来一轮新的机遇,借力鸿蒙系统完成应用创新。


服务入口不止是APP,用户在不下载APP的情况下,同样能畅享多种轻应用服务,建立起让用户感觉更亲密的认知和体验。 在全面到来的数字化时代,用户对服务的需求在不同场景及终端,逐步向智能化、便捷化、轻量化转变。


鸿蒙的出现,提供了更新的想象空间,尤其是超级终端理念、轻量化原子服务。


未来,鸿蒙系统带来的全新技术与服务方式,将会进一步加快产品与鸿蒙系统间的融合,从产品、技术、场景联合发力,打造出更多基于鸿蒙生态的特色服务场景。


酝酿了这么多,下面开始进入技术部分的正题,来尝尝鲜。


官方将服务卡片分为三方面:



卡片使用方


显示卡片内容的宿主应用,控制卡片在宿主中展示的位置。


卡片管理服务


用于管理系统中所添加卡片的常驻代理服务,包括卡片对象的管理与使用,以及卡片周期性刷新等。


卡片提供方


提供卡片显示内容的HarmonyOS应用或原子化服务,控制卡片的显示内容、控件布局以及控件点击事件


卡片使用方和提供方不要求常驻运行,在需要添加/删除/请求更新卡片时,卡片管理服务会拉起卡片提供方获取卡片信息。


卡片管理服务


周期性刷新:在卡片添加后,根据卡片的刷新策略启动定时任务周期性触发卡片的刷新。


卡片缓存管理:在卡片添加到卡片管理服务后,对卡片的视图信息进行缓存,以便下次获取卡片时可以直接返回缓存数据,降低时延。


卡片生命周期管理:对于卡片切换到后台或者被遮挡时,暂停卡片的刷新;以及卡片的升级/卸载场景下对卡片数据的更新和清理。


卡片使用方对象管理:对卡片使用方的RPC对象进行管理,用于使用方请求进行校验以及对卡片更新后的回调处理。


卡片提供方


创建卡片实例并实现onCreateForm、onUpdateForm和onDeleteForm处理创建卡片、更新卡片以及删除卡片等请求,提供相应的卡片服务。


服务卡片的实现:


官方文档,官方教程文档见Java卡片开发指导


运行DevEco Studio创建一个新项目,因为要使用java语言,选择支持Java语言。测试起见,选择个空的Ability页面。



接下来创建模板:右击“Entry”→“New”→“Server Widget”


创建完成之后,在代码的根目录下会自动创建一个widget的文件夹。且自动生成了一些相关代码。


在文件夹中出现了三个文件FormControllerManager.java、FormController.java、CardWidgetImpl.java。


三个文件对应了卡片服务的运行机制,通过关系的对应可以清楚的了解到代码运行原理。


FormControllerManager.java(卡片控制器管理--卡片服务管理)


public class FormControllerManager {
    private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, FormControllerManager.class.getName());
    private static final String PACKAGE_PATH = "com.example.carddemo.widget";
    private static final String SHARED_SP_NAME = "form_info_sp.xml";
    private static final String FORM_NAME = "formName";
    private static final String DIMENSION = "dimension";
    private static FormControllerManager managerInstance = null;
    private final HashMap<Long, FormController> controllerHashMap = new HashMap<>();
    private final Context context;
    private final Preferences preferences;
    /**
     * 初始化构造器
     *
     * @param context instance of Context.
     */
    private FormControllerManager(Context context) {
        this.context = context;
        DatabaseHelper databaseHelper = new DatabaseHelper(this.context.getApplicationContext());
        preferences = databaseHelper.getPreferences(SHARED_SP_NAME);
    }
    /**
     * FormControllerManager 实例化
     *
     * @param context instance of Context.
     * @return FormControllerManager instance.
     */
    public static FormControllerManager getInstance(Context context) {
        if (managerInstance == null) {
            synchronized (FormControllerManager.class) {
                if (managerInstance == null) {
                    managerInstance = new FormControllerManager(context);
                }
            }
        }
        return managerInstance;
    }
    /**
     * 通过构造器将传入的卡片信息进行封装,返回卡片服务
     *
     * @param formId    form id.
     * @param formName  form name.
     * @param dimension form dimension
     * @return FormController form controller
     */
    public FormController createFormController(long formId, String formName, int dimension) {
        synchronized (controllerHashMap) {
            if (formId < 0 || formName.isEmpty()) {
                return null;
            }
            HiLog.info(TAG,
                    "saveFormId() formId: " + formId + ", formName: " + formName + ", preferences: " + preferences);
            if (preferences != null) {
                ZSONObject formObj = new ZSONObject();
                formObj.put(FORM_NAME, formName);
                formObj.put(DIMENSION, dimension);
                preferences.putString(Long.toString(formId), ZSONObject.toZSONString(formObj));
                preferences.flushSync();
            }
            // Create controller instance.
            FormController controller = newInstance(formName, dimension, context);
            // Cache the controller.
            if (controller != null) {
                if (!controllerHashMap.containsKey(formId)) {
                    controllerHashMap.put(formId, controller);
                }
            }
            return controller;
        }
    }
    /**
     * 获取卡片控制器实例
     *
     * @param formId form id.
     * @return the instance of form controller.
     */
    public FormController getController(long formId) {
        synchronized (controllerHashMap) {
            if (controllerHashMap.containsKey(formId)) {
                return controllerHashMap.get(formId);
            }
            Map<String, ?> forms = preferences.getAll();
            String formIdString = Long.toString(formId);
            if (forms.containsKey(formIdString)) {
                ZSONObject formObj = ZSONObject.stringToZSON((String) forms.get(formIdString));
                String formName = formObj.getString(FORM_NAME);
                int dimension = formObj.getIntValue(DIMENSION);
                FormController controller = newInstance(formName, dimension, context);
                controllerHashMap.put(formId, controller);
            }
            return controllerHashMap.get(formId);
        }
    }
    private FormController newInstance(String formName, int dimension, Context context) {
        FormController ctrInstance = null;
        if (formName == null || formName.isEmpty()) {
            HiLog.error(TAG, "newInstance() get empty form name");
            return ctrInstance;
        }
        try {
            String className = PACKAGE_PATH + "." + formName.toLowerCase(Locale.ROOT) + "."
                    + getClassNameByFormName(formName);
            Class<?> clazz = Class.forName(className);
            if (clazz != null) {
                Object controllerInstance = clazz.getConstructor(Context.class, String.class, Integer.class)
                        .newInstance(context, formName, dimension);
                if (controllerInstance instanceof FormController) {
                    ctrInstance = (FormController) controllerInstance;
                }
            }
        } catch (NoSuchMethodException | InstantiationException | IllegalArgumentException | InvocationTargetException
                | IllegalAccessException | ClassNotFoundException | SecurityException exception) {
            HiLog.error(TAG, "newInstance() get exception: " + exception.getMessage());
        }
        return ctrInstance;
    }
    /**
     * 从数组中获取所有卡片id
     *
     * @return form id list
     */
    public List<Long> getAllFormIdFromSharePreference() {
        List<Long> result = new ArrayList<>();
        Map<String, ?> forms = preferences.getAll();
        for (String formId : forms.keySet()) {
            result.add(Long.parseLong(formId));
        }
        return result;
    }
    /**
     * 删除卡片服务
     *
     * @param formId form id
     */
    public void deleteFormController(long formId) {
        synchronized (controllerHashMap) {
            preferences.delete(Long.toString(formId));
            preferences.flushSync();
            controllerHashMap.remove(formId);
        }
    }
    private String getClassNameByFormName(String formName) {
        String[] strings = formName.split("_");
        StringBuilder result = new StringBuilder();
        for (String string : strings) {
            result.append(string);
        }
        char[] charResult = result.toString().toCharArray();
        charResult[0] = (charResult[0] >= 'a' && charResult[0] <= 'z') ? (char) (charResult[0] - 32) : charResult[0];
        return String.copyValueOf(charResult) + "Impl";
    }
}


FormController.java(卡片控制器--卡片提供方)


public abstract class FormController {
    protected final Context context;
    protected final String formName;
    protected final int dimension;
    public FormController(Context context, String formName, Integer dimension) {
        this.context = context;
        this.formName = formName;
        this.dimension = dimension;
    }
    /**
     * 创建卡片信息提供者
     */
    public abstract ProviderFormInfo bindFormData();
    /**
     * 更新卡片信息
     */
    public abstract void updateFormData(long formId, Object... vars);
    /**
     * 在接收服务小部件消息事件时调用
     */
    public abstract void onTriggerFormEvent(long formId, String message);
    /**
     * 获取路由的目标界面
     */
    public abstract Class<? extends AbilitySlice> getRoutePageSlice(Intent intent);
}


CardWidgetImpl.java(卡片应用--卡片使用方)


public class CardWidgetImpl extends FormController {
    public static final int DIMENSION_1X2 = 1;
    public static final int DIMENSION_2X4 = 3;
    private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, CardWidgetImpl.class.getName());
    private static final int DEFAULT_DIMENSION_2X2 = 2;
    private static final Map<Integer, Integer> RESOURCE_ID_MAP = new HashMap<>();
    static {
        RESOURCE_ID_MAP.put(DIMENSION_1X2, ResourceTable.Layout_form_grid_pattern_cardwidget_1_2);
        RESOURCE_ID_MAP.put(DEFAULT_DIMENSION_2X2, ResourceTable.Layout_form_grid_pattern_cardwidget_2_2);
        RESOURCE_ID_MAP.put(DIMENSION_2X4, ResourceTable.Layout_form_grid_pattern_cardwidget_2_4);
    }
    public CardWidgetImpl(Context context, String formName, Integer dimension) {
        super(context, formName, dimension);
    }
    //创建好卡片服务后,在界面展示卡片
    @Override
    public ProviderFormInfo bindFormData() {
        HiLog.info(TAG, "bind form data when create form");
        return new ProviderFormInfo(RESOURCE_ID_MAP.get(dimension), context);
    }
    //更新卡片信息
    @Override
    public void updateFormData(long formId, Object... vars) {
        HiLog.info(TAG, "update form data timing, default 30 minutes");
    }
    //卡片中内容手势触发方法
    @Override
    public void onTriggerFormEvent(long formId, String message) {
        HiLog.info(TAG, "handle card click event.");
    }
    @Override
    public Class<? extends AbilitySlice> getRoutePageSlice(Intent intent) {
        HiLog.info(TAG, "get the default page to route when you click card.");
        return null;
    }
}


MainAbility里自动新增了一些方法:


public class MainAbility extends Ability {
    public static final int DEFAULT_DIMENSION_2X2 = 2;
    public static final int DIMENSION_1X2 = 1;
    public static final int DIMENSION_2X4 = 3;
    public static final int DIMENSION_4X4 = 4;
    private static final int INVALID_FORM_ID = -1;
    private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, MainAbility.class.getName());
    private String topWidgetSlice;
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(MainAbilitySlice.class.getName());
        if (intentFromWidget(intent)) {
            topWidgetSlice = getRoutePageSlice(intent);
            if (topWidgetSlice != null) {
                setMainRoute(topWidgetSlice);
            }
        }
        stopAbility(intent);
    }
    //创建卡片信息并返回卡片内容
    @Override
    protected ProviderFormInfo onCreateForm(Intent intent) {
        HiLog.info(TAG, "onCreateForm");
        long formId = intent.getLongParam(AbilitySlice.PARAM_FORM_IDENTITY_KEY, INVALID_FORM_ID);
        String formName = intent.getStringParam(AbilitySlice.PARAM_FORM_NAME_KEY);
        int dimension = intent.getIntParam(AbilitySlice.PARAM_FORM_DIMENSION_KEY, DEFAULT_DIMENSION_2X2);
        HiLog.info(TAG, "onCreateForm: formId=" + formId + ",formName=" + formName);
        FormControllerManager formControllerManager = FormControllerManager.getInstance(this);
        FormController formController = formControllerManager.getController(formId);
        //通过调用布局Id将卡片布局与卡片信息进行绑定
        formController = (formController == null) ? formControllerManager.createFormController(formId,
                formName, dimension) : formController;
        if (formController == null) {
            HiLog.error(TAG, "Get null controller. formId: " + formId + ", formName: " + formName);
            return null;
        }
        return formController.bindFormData();
    }
    //更新卡片信息
    @Override
    protected void onUpdateForm(long formId) {
        HiLog.info(TAG, "onUpdateForm");
        super.onUpdateForm(formId);
        FormControllerManager formControllerManager = FormControllerManager.getInstance(this);
        FormController formController = formControllerManager.getController(formId);
        formController.updateFormData(formId);
    }
    //删除卡片
    @Override
    protected void onDeleteForm(long formId) {
        HiLog.info(TAG, "onDeleteForm: formId=" + formId);
        super.onDeleteForm(formId);
        FormControllerManager formControllerManager = FormControllerManager.getInstance(this);
        formControllerManager.deleteFormController(formId);
    }
    //卡片手势触发
    @Override
    protected void onTriggerFormEvent(long formId, String message) {
        HiLog.info(TAG, "onTriggerFormEvent: " + message);
        super.onTriggerFormEvent(formId, message);
        FormControllerManager formControllerManager = FormControllerManager.getInstance(this);
        FormController formController = formControllerManager.getController(formId);
        formController.onTriggerFormEvent(formId, message);
    }
    @Override
    public void onNewIntent(Intent intent) {
        if (intentFromWidget(intent)) { // Only response to it when starting from a service widget.
            String newWidgetSlice = getRoutePageSlice(intent);
            if (topWidgetSlice == null || !topWidgetSlice.equals(newWidgetSlice)) {
                topWidgetSlice = newWidgetSlice;
                restart();
            }
        }
    }
    private boolean intentFromWidget(Intent intent) {
        long formId = intent.getLongParam(AbilitySlice.PARAM_FORM_IDENTITY_KEY, INVALID_FORM_ID);
        return formId != INVALID_FORM_ID;
    }
    //跳转至对应的卡片界面
    private String getRoutePageSlice(Intent intent) {
        long formId = intent.getLongParam(AbilitySlice.PARAM_FORM_IDENTITY_KEY, INVALID_FORM_ID);
        if (formId == INVALID_FORM_ID) {
            return null;
        }
        FormControllerManager formControllerManager = FormControllerManager.getInstance(this);
        FormController formController = formControllerManager.getController(formId);
        if (formController == null) {
            return null;
        }
        Class<? extends AbilitySlice> clazz = formController.getRoutePageSlice(intent);
        if (clazz == null) {
            return null;
        }
        return clazz.getName();
    }
}


onCreateForm(Intent intent)


onUpdateForm(long formId)


onDeleteForm(long formId)


onCastTempForm(long formId)


onEventNotify(Map<Long, Integer> formEvents)


在onCreateForm(Intent intent)中,当卡片使用方请求获取卡片时,卡片提供方会被拉起并调onCreateForm(Intent intent)回调,intent中会带有卡片ID,卡片名称,临时卡片标记和卡片外观规格信息,分别通过


AbilitySlice.PARAM_FORM_IDENTITY_KEY、


AbilitySlice.PARAM_FORM_NAME_KEY、


AbilitySlice.PARAM_FORM_TEMORARY_KEY和


AbilitySlice.PARAM_FORM_DIMENSION_KEY按需获取。


提供方可以通过AbilitySlice.PARAM_FORM_CUSTOMIZE_KEY获取卡片使用方设置的自定义数据。当卡片使用方请求获取卡片时,卡片提供方会被拉起并调用onCreateForm回调函数,完成卡片信息的初始化。


onDeleteForm,当卡片被删除时,需要重写onDeleteForm方法,根据卡片id删除卡片实例数据。


卡片使用方:显示卡片内容的宿主应用,控制卡片在宿主中展示的位置。


卡片提供方:提供卡片显示内容的HarmonyOS Service/HarmonyOS Application,控制卡片的显示内容、控件布局以及控件点击事件。


配置文件config.json里也发生了一些变化。


可以对卡片的界面根据需要更改。


修改form_grid_pattern_cardwidget_1_2、form_grid_pattern_cardwidget_2_2.xml和form_grid_pattern_cardwidget_2_4.xml文件。


最后运行程序,可查看效果。点击图标上划,出现卡片。后续可以进一步完善。使其进行动态的刷新及动态的获取数据。比其传统的一个小应用图标,这种卡片的方式成了一种新的媒介窗口,更有活力和生命力,方便了用户的同时也连通了企业。


更多详细的介绍,参加官方文档:https://developer.harmonyos.com/cn/docs/design/des-guides/service-overview-0000001139795693


其中官方还有个ClockFACardDemo,值得学习。代码参见:https://gitee.com/openharmony/codelabs/tree/master/ClockFACardDemo


相关文章
|
4天前
|
JavaScript API 数据处理
基于HarmonyOS 5.0 (Next)技术的渐变模糊效果技术实现【代码实战】
本文详细介绍如何在HarmonyOS 5.0(Next)中实现渐变模糊效果,涵盖从基础页面搭建到添加模糊、渐变效果的全过程,并通过代码实战展示具体操作步骤。文章首先介绍了使用`Stack`和`Image`控件设置背景并应用`foregroundBlurStyle`属性实现模糊效果,接着通过`linearGradient`属性融入渐变效果,使界面更加精致美观。此外,还展示了如何利用滑动条和手势等交互元素动态调整模糊与渐变效果,增强用户体验。最后,通过具体代码示例说明如何为图片、弹窗等控件添加渐变模糊效果,突显HarmonyOS的强大功能与灵活性。
30 17
|
4天前
|
数据管理 API 调度
鸿蒙HarmonyOS应用开发 | 探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力
HarmonyOS Next 是华为新一代操作系统,专注于分布式技术的深度应用与生态融合。本文通过技术特点、应用场景及实战案例,全面解析其核心技术架构与开发流程。重点介绍分布式软总线2.0、数据管理、任务调度等升级特性,并提供基于 ArkTS 的原生开发支持。通过开发跨设备协同音乐播放应用,展示分布式能力的实际应用,涵盖项目配置、主界面设计、分布式服务实现及部署调试步骤。此外,深入分析分布式数据同步原理、任务调度优化及常见问题解决方案,帮助开发者掌握 HarmonyOS Next 的核心技术和实战技巧。
121 76
鸿蒙HarmonyOS应用开发 | 探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力
|
4天前
|
开发框架 人工智能 安全
鸿蒙HarmonyOS应用开发 | 「鸿蒙技术分享」HarmonyOS NEXT元服务卡片实战体验
HarmonyOS NEXT的发布对华为及整个行业都产生了深远的影响。它不仅展示了华为的技术实力,还敏锐地把握了市场需求。同时,吸引了更多的开发者和合作伙伴加入鸿蒙生态体系,共同推动鸿蒙生态的繁荣发展。
175 20
鸿蒙HarmonyOS应用开发 | 「鸿蒙技术分享」HarmonyOS NEXT元服务卡片实战体验
|
3天前
|
安全 数据安全/隐私保护 UED
HarmonyOS 5.0 (Next)应用开发实战:使用ArkTS构建开箱即用的登录页面【HarmonyOS 5.0(Next)】
### HarmonyOS 5.0(Next)应用开发实战:使用ArkTS构建开箱即用的登录页面 HarmonyOS 5.0(Next)融合了美学与科技,引入“光感美学”设计理念和多设备深度协同功能。本文通过 ArkTS 构建一个简单的登录页面,展示了模块化导入、状态管理、方法封装、声明式UI构建及事件处理等最佳实践。代码实现了一个包含用户名和密码输入框及登录按钮的界面,支持错误提示和页面跳转。
42 14
HarmonyOS 5.0 (Next)应用开发实战:使用ArkTS构建开箱即用的登录页面【HarmonyOS 5.0(Next)】
|
5天前
|
物联网 调度 vr&ar
鸿蒙HarmonyOS应用开发 |鸿蒙技术分享HarmonyOS Next 深度解析:分布式能力与跨设备协作实战
鸿蒙技术分享:HarmonyOS Next 深度解析 随着万物互联时代的到来,华为发布的 HarmonyOS Next 在技术架构和生态体验上实现了重大升级。本文从技术架构、生态优势和开发实践三方面深入探讨其特点,并通过跨设备笔记应用实战案例,展示其强大的分布式能力和多设备协作功能。核心亮点包括新一代微内核架构、统一开发语言 ArkTS 和多模态交互支持。开发者可借助 DevEco Studio 4.0 快速上手,体验高效、灵活的开发过程。 239个字符
150 13
鸿蒙HarmonyOS应用开发 |鸿蒙技术分享HarmonyOS Next 深度解析:分布式能力与跨设备协作实战
|
3天前
|
自然语言处理 搜索推荐 数据安全/隐私保护
鸿蒙登录页面好看的样式设计-HarmonyOS应用开发实战与ArkTS代码解析【HarmonyOS 5.0(Next)】
鸿蒙登录页面设计展示了 HarmonyOS 5.0(Next)的未来美学理念,结合科技与艺术,为用户带来视觉盛宴。该页面使用 ArkTS 开发,支持个性化定制和无缝智能设备连接。代码解析涵盖了声明式 UI、状态管理、事件处理及路由导航等关键概念,帮助开发者快速上手 HarmonyOS 应用开发。通过这段代码,开发者可以了解如何构建交互式界面并实现跨设备协同工作,推动智能生态的发展。
38 10
鸿蒙登录页面好看的样式设计-HarmonyOS应用开发实战与ArkTS代码解析【HarmonyOS 5.0(Next)】
|
3天前
|
人工智能 安全 数据安全/隐私保护
HarmonyOS应用开发实战:基于ArkTS的开箱即用登录页面实现【样式方式实现①】【HarmonyOS 5.0(Next)】
本文介绍了基于HarmonyOS 5.0(Next)和ArkTS实现的开箱即用登录页面。HarmonyOS 5.0是华为于2024年10月22日发布的第三代移动操作系统,具备原生智能、互联、安全及流畅特性。文章详细解析了使用ArkTS开发登录页面的代码,涵盖组件定义、界面布局、事件处理、样式设置及异步操作等内容,展示了清晰的组件结构、响应式设计与模块化编程的优势。通过这段代码,开发者可以快速上手并构建高效、美观的应用界面。
|
1天前
【HarmonyOS Next开发】:ListItemGroup使用
通过使用ListItemGroup和AlphabetIndexer两种类型组件,实现带标题分类和右侧导航栏的页面
82 61
|
1天前
|
开发者
【HarmonyOS Next开发】用户文件访问
文件所有者为登录到该终端设备的用户,包括用户私有的图片、视频、音频、文档等。 应用对用户文件的创建、访问、删除等行为,需要提前获取用户授权,或由用户操作完成。
20 10
|
1天前
|
存储 JSON 测试技术
【HarmonyOS Next开发】云开发-云数据库(二)
实现了云侧和端侧的云数据库创建、更新、修改等操作。这篇文章实现调用云函数对云数据库进行增删改查。
19 9

热门文章

最新文章