> 文档中心 > 鸿蒙界面跳转

鸿蒙界面跳转

概述

HarmonyOS应用开发中的Ability相当于一个容器,容器中可以存放多个AbilitySlice。一个Ability相当于一个page,一个AbilitySlice相当于page中的一个子页面,一个应用中可以有多个Ability。本文主要介绍的是同一个Ability中不同AbilitySlice之间的跳转,及不同Ability中的AbilitySlice之间的跳转。

准备
文中涉及到多个Ability和AbilitySlice,所以需要提前准备好,使用的时候创建也可以。

创建Ability
创建Ability继承Ability即可
public class SecondAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(SecondAbilitySlice.class.getName());
        ...
    }
}

项目中已经自动创建了MainAbility,再创建一个SecondAbility即可。

创建AbilitySlice
创建AbilitySlice需要继承AbilitySlice
public class MainAbilitySlice1 extends AbilitySlice {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main_1);
        ...
    }
  ...
}

这里根据需要分别创建了MainAbilitySlice1,MainAbilitySlice2,SecondAbilitySlice,SecondAbilitySlice1。

添加路由
AbilitySlice创建完后需要在Ability中添加相对应的路由。
public class MainAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(MainAbilitySlice.class.getName());

        addActionRoute("main_slice1",MainAbilitySlice1.class.getName());
        addActionRoute("main_slice2", MainAbilitySlice2.class.getName());

    }
}

setMainRoute是设置Ability中的主页面,而addActionRoute则是添加其他页面。addActionRoute中第一个参数则是需要在config.json中先声明,然后在Ability中使用才会有效。

    "abilities": [
      {
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home",
              "main_slice1",
              "main_slice2"
            ]
          }
        ],
        "orientation": "unspecified",
        "name": "com.harmonyos.pages.MainAbility",
        "icon": "$media:icon",
        "description": "$string:mainability_description",
        "label": "$string:app_name",
        "type": "page",
        "launchType": "standard"
      },
      ...

需要在skills中actions中添加。SecondAbility 也是如此。

分类
根据跳转类型的不同,可以大致分为三类:无参跳转、有参跳转、含返回参跳转。具体细分可以分为同一Ability中的不同AbilitySlice之间的无参、有参和含返回参跳转,不同Ability之间的无参、有参和含返回参跳转。

同一Ability中不同AbilitySlice之间的无参跳转
AbilitySlice跳转通常使用Intent。
        Text mainPage = (Text) findComponentById(ResourceTable.Id_main_page_without_param);
        mainPage.setClickedListener(component -> {
            // 同page之间的无参跳转
            Intent intent1 = new Intent();
            present(new MainAbilitySlice1(),intent1);

        });

发现组件并添加点击事件。

效果

同一Ability中不同AbilitySlice之间的带参跳转
添加信息
带参跳转,这里以携带简单的字符串为例,先将需要携带的信息添加进Intent中。
        findComponentById(ResourceTable.Id_main_page_with_param).setClickedListener(component -> {
            // 同page之间的带参跳转
            Intent intent1 = new Intent();
            intent1.setParam("param", "MainPage向MainPage2携带的参数");
            present(new MainAbilitySlice2(), intent1);
        });

接受信息
在MainAbilitySlice2中接收信息并解析。
      Text mainPage2 = (Text) findComponentById(ResourceTable.Id_main_page2);
        if(intent != null){
            String param = intent.getStringParam("param");
            mainPage2.setText(param);
        }

效果

同一Ability中不同AbilitySlice之间的含返回参跳转
添加跳转数据
跳转出发页可以携带信息,也可以不携带信息,这里以携带信息为例
        mainPageForResult = (Text) findComponentById(ResourceTable.Id_main_page_for_result);
        mainPageForResult.setClickedListener(component -> {
            // 同page之间的带返回参跳转
            Intent intent1 = new Intent();
            intent1.setParam("param","param");
            presentForResult(new MainAbilitySlice1(),intent1,520);
        });

和之前不同之处在与这里使用的是presentForResult,而不是present,同时还需要设置requestCode,这里设置为520。设置requestCode是为了区分信息来源,以免有多个信息的时候产生混淆。

添加返回数据
        findComponentById(ResourceTable.Id_main_page1).setClickedListener(component -> {
                // 带参返回
                Intent intent2 = new Intent();
                intent2.setParam("back","这是MainAbilitySlice1返回给MainAbilitySlice的数据");
                setResult(intent2);
                terminate();
        });

terminate结束当前页面,setResult是页面结束的时候将信息返回。

接收返回的信息
    @Override
    protected void onResult(int requestCode, Intent resultIntent) {
        super.onResult(requestCode, resultIntent);
        if(requestCode == 520){
            String result = resultIntent.getStringParam("back");
            mainPageForResult.setText(result);
        }
    }

在接收返回信息的页面中重写onResult方法,对返回的信息进行解析。

效果

不同Ability中不同AbilitySlice之间的无参跳转
跳转
        findComponentById(ResourceTable.Id_main_page_goto_other_page).setClickedListener(component -> {
            // 不同page无参跳转
            Intent intent1 = new Intent();
            Operation builder = new Intent.OperationBuilder()
                    .withBundleName("com.harmonyos.pages")
                    .withAbilityName(".SecondAbility")
                    .withDeviceId("")
                    .build();

            intent1.setOperation(builder);
            startAbility(intent1);
        });

和同一Ability不同的是这是使用的是startAbility,而不是present。builder使用的时候需要注意类型,withAbilityName中以"."开头是因为前面的名称和”com.harmonyos.pages“一致,所以可以省略。withBundleName里面需要填写的内容可以在config.json中找到,一般就是包名。withDeviceId中填写空字符,是因为填写空字符时程序可以自动获取当前设备id。

效果

不同Ability中不同AbilitySlice之间的带参跳转
跳转
        findComponentById(ResourceTable.Id_main_page_goto_other_page_with_param).setClickedListener(component -> {
            // 不同page带参跳转
            Intent intent1 = new Intent();
            intent1.setParam("param","MainPage向SecondPage携带的参数");
            Operation builder = new Intent.OperationBuilder()
                    .withAbilityName(".SecondAbility")
                    .withBundleName("com.harmonyos.pages")
                    .withDeviceId("")
                    .build();

            intent1.setOperation(builder);
            startAbility(intent1);
        });

携带的数据和之前的一样,添加到Intent中就行,Intent中添加的数据类型不止String类型,基本数据类型,数列化等数据都支持,可满足99%的需求。

效果

不同Ability中不同AbilitySlice之间的含返回参跳转
跳转前
        mainPageGotoOtherPageForResult.setClickedListener(component -> {
            // 不同page带返回参跳转
            Intent intent1 = new Intent();
            Operation builder = new Intent.OperationBuilder()
                    .withAbilityName(".SecondAbility")
                    .withBundleName("com.harmonyos.pages")
                    .withDeviceId("")
                    .build();

            intent1.setOperation(builder);
            startAbilityForResult(intent1,521);
        });

在MainAbilitySlice中使用startAbilityForResult,并设置requestCode为521,然后跳转至SecondAbility。

跳转后
        Text secondPage = (Text) findComponentById(ResourceTable.Id_second_page);
        secondPage.setClickedListener(component -> {
            Intent intent1 = new Intent();
            intent1.setParam("result","result");
            getAbility().setResult(520,intent1);
            terminate();

        });
在SecondAbility中设置返回数据为”result“,然后使用terminate方法结束SecondAbility,并设置resultCode为520。注意使用的是getAbility().setResult,而不是setResult,否则消息发送不成功。

接收返回参数
    @Override
    protected void onAbilityResult(int requestCode, int resultCode, Intent resultData) {
        super.onAbilityResult(requestCode, resultCode, resultData);
        if(requestCode == 521 && resultCode == 520){
            String result = resultData.getStringParam("result");
           // 可以对数据进行判空,防止空指针
            mainPageGotoOtherPageForResult.setText(result);
        }
    }

重写onAbilityResult,然后匹配requestCode和resultCode,对返回数据进行解析。

效果

不同Ability中非主AbilitySlice之间的跳转
跳转前
        Text mainPage2 = (Text) findComponentById(ResourceTable.Id_main_page2);
        mainPage2.setClickedListener(component -> {
            Intent intent1 = new Intent();
            intent1.setAction("second_slice1");
            startAbility(intent1);
        });

这里的跳转是从MainAbilitySlice2跳转至SecondAbilitySlice1,两个页面都不是MainRoute,当然这里面也分带参,不带参和携带返回参,操作和前面一样,这里就不一一描述了。注意second_slice1需要提前在config.json中声明,否则该字符串无意义。

效果

总结
不同页面之间的跳转及数据传递基本上和Android中一样。
Ability和Android中的Activity差不多,AbilitySlice相当于Android中的Fragment,但是使用要比Fragment灵活多样。
对于Android开发者来讲,鸿蒙应用开发对其是天然友好。

由于没有鸿蒙的设备,所以效果图中使用的手机均为远程模拟器。