HarmonyOS - 服务卡片进阶(二) 原创 精华

中软小助手
发布于 2022-5-6 10:30
浏览
2收藏

作者:贾叶照

前言

HarmonyOS - 服务卡片进阶(一)之后,补充关于服务卡片信息持久化、卡片控制事件的内容。

服务卡片信息持久化

  • 因大部分卡片提供方都不是常驻服务,只有在需要使用时才会被拉起获取卡片信息。且卡片管理服务支持对卡片进行多实例管理,卡片ID对应实例ID,因此若卡片提供方支持对卡片数据进行配置,则需要提供方对卡片的业务数据按照卡片ID进行持久化管理,以便在后续获取、更新以及拉起时能获取到正确的卡片业务数据。同时,需要适配onDeleteForm(int formId)卡片删除通知接口,在其中实现卡片实例数据的删除。
  • 和JS卡片相同,需要注意卡片使用方在请求卡片时传递给提供方应用的Intent数据中存在临时标记字段,表示此次请求的卡片是否为临时卡片,由于临时卡片的数据具有非持久化的特殊性,某些场景比如卡片服务框架死亡重启,此时临时卡片数据在卡片管理服务中已经删除,且对应的卡片ID不会通知到提供方,所以卡片提供方需要自己负责清理长时间未删除的临时卡片数据。同时对应的卡片使用方可能会将之前请求的临时卡片转换为常态卡片。如果转换成功,卡片提供方也需要对对应的临时卡片ID进行处理,把卡片提供方记录的临时卡片数据转换为常态卡片数据,防止提供方在清理长时间未删除的临时卡片时,把已经转换为常态卡片的临时卡片信息删除,导致卡片信息丢失。
  //临时标记字段,表示此次请求的卡片是否为临时卡片
        boolean tempFlag = intent.getBooleanParam(AbilitySlice.PARAM_FORM_TEMPORARY_KEY, false);

  • 常态卡片:卡片使用方会持久化的卡片;
  • 临时卡片:卡片使用方不会持久化的卡片;

临时卡片转换为常态卡片触发

   protected void onCastTempForm(long formId) {
        // 使用方将临时卡片转换为常态卡片触发,提供方需要做相应的处理
        super.onCastTempForm(formId);
        //todo
    }

将创建的卡片信息持久化,以便在下次获取/更新该卡片实例时进行使用。

 // 将卡片信息存入数据库
  saveFormInfo(formId, formName, dimension);

  private void saveFormInfo(Long formId, String formName, int dimension) {
        FormInfo form = new FormInfo(formId, formName, dimension);
        DatabaseUtils.insertForm(this, form);
    }

关于OrmDatabase对象型数据库部分我们可以参考肖瑜博老师我们带来的HarmonyOS-十分钟教会数据库快速上手这篇文章,里面详细介绍了关于对象型数据库的配置、创建数据库、表、对应实体类的属性以及ormContext的创建。

Java卡片控制事件

Java卡片当前通过IntentAgent能力支持对卡片控制设置事件,例如可以使用START_ABILITY、START_SERVICE这两类能力,在点击整张卡片时,跳转到提供卡片的ability。(注:Intent中支持自定义参数的传递,支持的类型有int/long/String/List)

    // 获取ComponentProvider,渲染卡片界面
    @Override
    protected ProviderFormInfo onCreateForm(Intent intent) {
        HiLog.info(TAG, "onCreateForm");
        // 卡片id
        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 + ",dimension=" + dimension);
        // 将卡片信息存入数据库
        saveFormInfo(formId, formName, dimension);

        // 开发者需要根据卡片的名称以及外观规格获取对应的xml布局并构造卡片对象,此处ResourceTable.Layout_form_weather_widget_2_2
        ProviderFormInfo formInfo = new ProviderFormInfo(ResourceTable.Layout_form_weather_widget_2_2, this);
        //获取此 ProviderFormInfo 对象中包含的ComponentProvider数据。
        ComponentProvider componentProvider = formInfo.getComponentProvider();
        //设置组件的文本内容
        componentProvider.setText(ResourceTable.Id_weather_text,  "天气:多云");
        componentProvider.setText(ResourceTable.Id_weather_temperature,  "温度:29度");
        componentProvider.setText(ResourceTable.Id_weather_ph,  "PH值:2.9");

        // 针对title控件设置事件
        componentProvider.setIntentAgent(ResourceTable.Id_weather_text, startAbilityIntentAgent());

        //将ComponentProvider中指定的操作合并到此ProviderFormInfo对象中包含的 ComponentProvider 对象中
        formInfo.mergeActions(componentProvider);
        return formInfo;
    }

以上我们可以通过componentProvider 的setIntentAgent方法给卡片上的组件设置点击事件,第一个参数为组件的资源id,第二个参数为IntentAgent对象,示例代码如下:

    componentProvider.setIntentAgent(ResourceTable.Id_weather_text, startAbilityIntentAgent());

获取IntentAgent对象,示例代码如下:

    private IntentAgent startAbilityIntentAgent() {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName("com.example.weatherservicecard")
                .withAbilityName("com.example.weatherservicecard.MainAbility")
                .build();
        intent.setOperation(operation);
        List<Intent> intentList = new ArrayList<>();
        intentList.add(intent);
        IntentAgentInfo paramsInfo = new IntentAgentInfo(200, IntentAgentConstant.OperationType.START_ABILITY,  IntentAgentConstant.Flags.UPDATE_PRESENT_FLAG, intentList, null);
        IntentAgent intentAgent = IntentAgentHelper.getIntentAgent(this, paramsInfo);
        return intentAgent;
    }

通过以上方式,我们就可以给卡片的每个组件设置点击事件,跳转到不同的页面了。
IntentAgentInfo方法参数解说:
public IntentAgentInfo(int requestCode, IntentAgentConstant.OperationType operationType, List < IntentAgentConstant.Flags > flags, List < Intent > intents, IntentParams extraInfo)
参数说明

  • requestCode:表示要设置的请求代码。它是用户定义的私有值。
  • operationType:指示 IntentAgent 对象要执行的操作的类型。取值范围详见IntentAgentConstant.OperationType。
  • flags: 指示用于处理 IntentAgent 的标志。取值范围详见IntentAgentConstant.Flags。
  • intents: 指示用于创建 IntentAgent 对象的 Intent 对象的集合。集合中的意图数量由IntentAgentConstant.OperationType确定。
  • extraInfo:指示用于创建 IntentAgent 对象的额外信息。

总结

1.卡片信息持久化目的是在使用方删除/定时定点更新卡片时,提供方能够根据卡片的ID删除/更新对应的业务数据,还有就是针对

​ 1)临时卡片:卡片提供方需要自己负责清理长时间未删除的临时卡片数据。

​ 2)临时卡片转换为常态卡片:防止提供方在清理长时间未删除的临时卡片时,把已经转换为常态卡片的临时卡片信息删除,导致卡片信息丢失。

2.卡片控制事件目的是实际应用中可能需要针对卡片中的各个组件设置对应的点击事件,跳转不同的页面。具体使用见以上说明。

关于原子化服务卡片信息分享暂时在这里告一段落了,以后若遇到服务卡片的其它应用场景会继续补充,谢谢!

更多原创内容请关注:中软国际 HarmonyOS 技术团队

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-5-6 10:31:10修改
1
收藏 2
回复
举报
1条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

学习老师不断总结完善的精神

回复
2022-5-6 10:35:24
回复
    相关推荐