前面講完官方的14種Contracts
,但我們也能建立屬於自己的Contracts
,以下範例是實作一個跟ActivityResultContracts.StartActivityForResult()
一樣功能的Contracts
,差別在於這次傳入的是Bundle
,回傳一樣是武器名稱
建立LancerActivity
、LancerActivityResultContract
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