1.概要
startActivityForResultが非推奨になり、その代替えとしてregisterForActivityResultが推奨されたので、様々なアクティビティーの作り方ごとに、その使い方を具体的にまとめた。
2.参考資料(ホームページアドレスや書籍)
本記事を作成するにあたり、次のサイトとリポジトリを参考にした。
・AndroidのstartActivityForResultに変わる新しいAPIが追加されました
・Android デベロッパードキュメントガイド
・startActivityForResult / requestPermissions が deprecated になる話
・https://github.com/nanaten/Activity[-Contract-Example
・掌田著 Android Jetpackプログラミング
・金田著 はじめてのAndroidプログラミング(第4版、第5版)
・山田著 Androidアプリ開発(第3版)
・斎藤著 Androidアプリ開発の教科書Kotlin対応(初版)
3.registerForActivityResultを使う上で必ず行うべきこと
registerForActivityResultを使うためには、必ずbuild.gradleに以下を追加する。(ただし、今回はFragmentを使わないので、fragmet-ktxの方は追加しなくてもよい。)
dependencies {
// (省略)
implementation "androidx.activity:activity-ktx:1.2.0-alpha04"
implementation "androidx.fragment:fragment-ktx:1.3.0-alpha03"
// (省略)
}
4.様々なアクティビティの作り方におけるregisuterForActivityResultの使い方
次の6つのアクティビティの作り方で、regisuterForActivityResultの使い方の使い方を試した。
ver.01 レイアウトUIへのアクセスにfindView()でViewのインスタンスを生成し、
リスナークラスをインナークラスで作る方法
ver.02 リスナークラスをObject式を用いて記述して作る方法
ver.03 リスナークラスのonClick関数をレイアウトファイルのonClick属性に設定する方法
ver.04 レイアウトUIへのアクセスに、Kotlin-Android-Extensions(KAE)を利用し、
setOnClickListenerにSAM変換方法を用いる方法
ver.05 レイアウトUIへのアクセスに、ViewBindingを用いる方法
ver.06 レイアウトUIへのアクセスに、DataBindingを用いる方法
なお、レイアウトファイルは基本的に次のファイルを使い、ver.03のレイアウトファイルのonClick属性のバージョンとver.06のDataBindingのバージョンについては、適宜変更を行う。
基本的なレイアウトファイル:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btnMain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="サブ画面へ">
</Button>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/etMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text">
</EditText>
<Button
android:id="@+id/btnBack"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="メイン画面へ" >
</Button>
</LinearLayout>
以上のレイアウトファイルを実行したときに表示される画面は以下の通り。
4.1 レイアウトUIへのアクセスにfindView()でViewのインスタンスを生成し、リスナークラスをインナークラスで作る方法(ver.01)
class MainActivity : AppCompatActivity() {
// registerForActivityResult を定義する
val getContent =
registerForActivityResult(StartActivityForResult()) { result: ActivityResult ->
// 呼び出し先のActivityを閉じた時に呼び出されるコールバックを登録
// (呼び出し先で埋め込んだデータを取り出して処理する)
if (result.resultCode == Activity.RESULT_OK) {
// RESULT_OK時の処理
val resultIntent = result.data
val message = resultIntent?.getStringExtra("message")
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// registerForActivityResult を定義する
val btnMain = findViewById<Button>(R.id.btnMain)
// ボタンをタップした時の処理
val listener = BtnSendListener()
btnMain.setOnClickListener(listener)
}
// リスナークラス
private inner class BtnSendListener : View.OnClickListener {
override fun onClick(v: View?) {
// registerForActivityResult を定義する
val requestIntent = Intent(applicationContext, SubActivity::class.java)
// SubActivityを起動
getContent.launch(requestIntent)
}
}
}
class SubActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sub)
val btnBack = findViewById<Button>(R.id.btnBack)
val listener = BtnBackSendListener()
btnBack.setOnClickListener(listener)
}
// リスナークラス
private inner class BtnBackSendListener : View.OnClickListener {
override fun onClick(v: View?) {
val etMessage: EditText = findViewById(R.id.etMessage)
// インテントにetMessageのtextをセット
intent.putExtra("message", etMessage.text.toString())
// 結果をセット
setResult(Activity.RESULT_OK, intent)
finish()
}
}
}
4.2 リスナークラスをObject式を用いて記述して作る方法(ver.02)
class MainActivity : AppCompatActivity() {
val getContent =
registerForActivityResult(StartActivityForResult()) { result: ActivityResult ->
// 呼び出し先のActivityを閉じた時に呼び出されるコールバック
if (result.resultCode == Activity.RESULT_OK) {
// RESULT_OK時の処理
val resultIntent = result.data
val message = resultIntent?.getStringExtra("message")
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btnMain = findViewById<Button>(R.id.btnMain)
btnMain.setOnClickListener(
object : View.OnClickListener {
override fun onClick(v: View?) {
// registerForActivityResult を定義する
val requestIntent = Intent(applicationContext, SubActivity::class.java)
getContent.launch(requestIntent)
}
}
)
}
}
class SubActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sub)
val btnBack = findViewById<Button>(R.id.btnBack)
btnBack.setOnClickListener(
object: View.OnClickListener {
override fun onClick(v: View?) {
val etMessage: EditText = findViewById(R.id.etMessage)
// インテントにetMessageのtextをセット
intent.putExtra("message", etMessage.text.toString())
// 結果をセット
setResult(Activity.RESULT_OK, intent)
finish()
}
}
)
}
}
4.3 リスナークラスのonClick関数をレイアウトファイルのonClick属性に設定する方法(ver.03)
class MainActivity : AppCompatActivity() {
// registerForActivityResult を定義する
val getContent =
registerForActivityResult(StartActivityForResult()) { result ->
// 呼び出し先のActivityを閉じた時に呼び出されるコールバック
if (result.resultCode == Activity.RESULT_OK) {
// RESULT_OK時の処理
val resultIntent = result.data
val message = resultIntent?.getStringExtra("message")
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
// ボタンをタップした時の処理
fun btnSend_onClick(v: View) {
// registerForActivityResult を定義する
val requestIntent = Intent(applicationContext, SubActivity::class.java)
// SubActivityを起動
getContent.launch(requestIntent)
}
}
class SubActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sub)
}
fun btnBack_onClick(v: View) {
val etMessage: EditText= findViewById(R.id.etMessage)
// インテントにetMessageのtextをセット
intent.putExtra("message", etMessage.text.toString())
// 結果をセット
setResult(Activity.RESULT_OK, intent)
finish()
}
}
また、setOnClickListener()メソッドの機能をレイアウトファイルに埋め込むためにonClick属性をレイアウトファイルに追記する。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
(省略)
<Button
android:id="@+id/btnMain"
(省略)
android:onClick="btnSend_onClick" <--追記
android:text="サブ画面へ">
</Button>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
(省略)
<Button
android:id="@+id/btnBack"
(省略)
android:onClick="btnBack_onClick" <--追記
android:text="メイン画面へ" >
</Button>
</LinearLayout>
4.4 レイアウトUIへのアクセスに、Kotlin-Android-Extensions(KAE)を利用し、setOnClickListenerにSAM変換方法を用いる方法(ver.04)
KAEを利用するためには、先ずbuild.gradle(:app)のplugingsにKotlinアンドロイド拡張プラグインを追記する。
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions' // 追記
}
またMainActivity.ktとSubActivity.ktは以下のとおり。但し、レイアウトファイルは基本レイアウトと同じである。
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
// registerForActivityResult を定義する
val getContent =
registerForActivityResult(StartActivityForResult()) { result: ActivityResult ->
// 呼び出し先のActivityを閉じた時に呼び出されるコールバック
if (result.resultCode == Activity.RESULT_OK) {
val resultIntent = result.data
val message = resultIntent?.getStringExtra("message")
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// ボタンをタップした時の処理
btnMain.setOnClickListener {
val requestIntent = Intent(this, SubActivity::class.java)
// SubActivityを起動
getContent.launch(requestIntent)
}
}
}
import kotlinx.android.synthetic.main.activity_sub.* // Kotlinアンドロイド拡張のためのインポート
class SubActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sub)
btnBack.setOnClickListener {
// インテントにetMessageのtextをセット
intent.putExtra("message", etMessage.text.toString())
// 結果をセット
setResult(Activity.RESULT_OK, intent)
finish()
}
}
}
4.5 レイアウトUIへのアクセスに、ViewBindingを用いる方法(ver.05)
以下のようにViewBingdingを利用するために、build.gradle(:app)のandoroi{……}の中にbuildFeatures{……}を追記し、ViewBindingを有効にする。
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
(省略)
buildFeatures{ //追記
viewBinding = true
}
}
class MainActivity : AppCompatActivity() {
// registerForActivityResult を定義する
val getContent =
registerForActivityResult(StartActivityForResult()) { result: ActivityResult ->
// 呼び出し先のActivityを閉じた時に呼び出されるコールバック
if (result.resultCode == Activity.RESULT_OK) {
// RESULT_OK時の処理
val resultIntent = result.data
val message = resultIntent?.getStringExtra("message")
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ViewBindingを定義する
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
// ボタンをタップした時の処理
binding.btnMain.setOnClickListener {
// registerForActivityResult を定義する
val requestIntent = Intent(applicationContext, SubActivity::class.java)
// SubActivityを起動
getContent.launch(requestIntent)
}
}
}
class SubActivity : AppCompatActivity() {
private lateinit var binding: ActivitySubBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySubBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.btnBack.setOnClickListener {
// インテントにetMessageのtextをセット
intent.putExtra("message", binding.etMessage.text.toString())
// 結果をセット
setResult(Activity.RESULT_OK, intent)
finish()
}
}
}
##4.6 レイアウトUIへのアクセスに、DataBindingを用いる方法(ver.06)
以下のようにDataBingdingを利用するために、build.gradle(:app)のandoroi{……}の中にbuildFeatures{……}を追記し、DataBindingを有効にする。
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
(省略)
buildFeatures{ //追記
DataBinding = true
}
}
class MainActivity : AppCompatActivity() {
// registerForActivityResult を定義する
val getContent =
registerForActivityResult(StartActivityForResult()) { result: ActivityResult ->
// 呼び出し先のActivityを閉じた時に呼び出されるコールバック
if (result.resultCode == Activity.RESULT_OK) {
// RESULT_OK時の処理
val resultIntent = result.data
val message = resultIntent?.getStringExtra("message")
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// dataBindingを定義する
val binding: ActivityMainBinding = DataBindingUtil
.setContentView(this, R.layout.activity_main)
// ボタンをタップした時の処理
binding.btnMain.setOnClickListener {
// registerForActivityResult を定義する
val requestIntent = Intent(applicationContext, SubActivity::class.java)
// SubActivityを起動
getContent.launch(requestIntent)
}
}
}
class SubActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// dataBindingを定義する
val binding: ActivitySubBinding = DataBindingUtil
.setContentView(this, R.layout.activity_sub)
binding.btnBack.setOnClickListener{
// インテントにetMessageのtextをセット
intent.putExtra("message", binding.etMessage.text.toString())
// 結果をセット
setResult(Activity.RESULT_OK, intent)
finish()
}
}
}