110/07 - 建立自己的 ResultContracts

前面讲完官方的14种Contracts,但我们也能建立属於自己的Contracts,以下范例是实作一个跟ActivityResultContracts.StartActivityForResult()一样功能的Contracts,差别在於这次传入的是Bundle,回传一样是武器名称

建立LancerActivityLancerActivityResultContract
MainActivity透过LancerActivityResultContract跳到LancerActivity时会带姓名
LancerActivity离开页面後会回传武器

MainActivity画面如下

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    tools:context=".MainActivity">

    <com.google.android.material.button.MaterialButton 
        android:id="@+id/amMbLancer"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:text="跳转 LancerActivity"
        android:textAllCaps="false"
        app:layout_constraintDimensionRatio="5:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/amMbSaber" />
</androidx.constraintlayout.widget.ConstraintLayout>

LancerActivity画面如下

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".LancerActivity">

    <com.google.android.material.button.MaterialButton
        android:id="@+id/alMbMain"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="8dp"
        android:text="跳转 Main 回传 Gae Bolg"
        android:textAllCaps="false"
        app:layout_constraintDimensionRatio="5:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

跳转後的程序码

class LancerActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_lancer)

        val bundle = intent.extras
        val name = bundle?.getString(BaseConstants.NAME)
        val gender = bundle?.getString(BaseConstants.GENDER)

        Log.d("maho", "姓名: $name / 性别:$gender")

        initClickListener()
    }

    private fun initClickListener() {
        alMbMain.setOnClickListener {

            val intent = Intent().apply {
                this.putExtra(BaseConstants.WEAPON, "Gae Bolg")
            }

            setResult(RESULT_OK, intent)
            finish()
        }
    }
}

建立合约Contract类别,名称为LancerActivityResultContract,需要继承ActivityResultContract<input, output>,程序码如下

class LancerActivityResultContract : ActivityResultContract<Bundle, String>() {
    override fun createIntent(context: Context, input: Bundle): Intent {
        return Intent(context, LancerActivity::class.java).apply {
            putExtras(input)
        }
    }

    override fun parseResult(resultCode: Int, intent: Intent?): String {
        val weapon = intent?.getStringExtra(BaseConstants.WEAPON)

        return if (Activity.RESULT_OK == resultCode && null != weapon) {
            weapon
        } else {
            BaseConstants.STRING_EMPTY
        }
    }
}

所以自定义合约Contract很简单,只要决定好输入和输出的型态就好,而且把Result拉出来做成类别後,也比较好找程序码,不用去Activity

建立好LancerActivityResultContract後,和之前的写法一样,去MainActivity,把合约Contract和启动器Launcher实作出来就好,程序码如下

val bundle = Bundle()
bundle.putString(BaseConstants.NAME, "CuChulainn")
bundle.putString(BaseConstants.GENDER, "male")

lancerActivityResultContract.launch(bundle)
private val lancerActivityResultContract =
    registerForActivityResult(LancerActivityResultContract()) { weapon ->
        Log.d("maho", "回传: $weapon")
    }

实际执行程序後的Log

D/maho: 姓名: CuChulainn / 性别:male
D/maho: 回传: Gae Bolg

程序码放在feature/createContracts分支
https://github.com/AndyAWD/AndroidSystem/tree/feature/createContracts


<<:  Day.9 进入 ARM 世界: ARM Cortex-M 暂存器介绍

>>:  [Day 09] Sass - Print

Day30 D3js 浪漫突进的回顾及展望

D3js 浪漫突进的回顾及展望 你只要顾好你会的、你喜欢的,一直讲、拼命讲,展现你的魅力! -- 浪...

[3D地图-CesiumJS系列] 三、车辆废气排放地图 - 以粒子系统(Particle system)实作

本篇文章请搭配 [3D地图-CesiumJS系列] 一、快速上手 [3D地图-CesiumJS系列]...

【Side Project】 点菜单功能实作 - Modal

今天这篇我们要来完成一些客户点菜单上的功能。 点菜单里面的功能很简单,就是把我们点餐的资料送到老板手...

Day04 - 在 GCE 建立第一个 Web Service

在 Day03 我们使用 GCE 建立一台 VM,今天要学习如何连线到虚拟机,并在服务器上使用 No...

Day 12 运算宝石:【Lab】EC2储存资源 EBS Volume 建立与使用 (上)

今天我们要介绍 EC2 搭配 EBS 储存资源的实际操作,那我们开始吧! 建立 VPC 环境 我们...