Android kotlin Activity間のオブジェクトの受け渡し


"intent object 渡す"とかでググると色々ヒットするが、渡されたオブジェクトは呼び出し先で新しく生成されたオブジェクトとして扱われることを備忘として書いておく。

例えば、以下のような定義のオブジェクトを渡す場合

class DataState(
    var data:String = ""
):Serializable{
    fun funcA(){}
}

呼び出し元

val intent = Intent( this, toActivity::class.java)
//this.dataStateはメンバに宣言
this.dataState = DataState("origin data")
Log.d( "sendObject::", dataState.toString() )
intent.putExtra("dataState", dataState)
startActivity(intent)

呼び出し先

val dataState = intent.getSerializableExtra("dataState") as DataState
Log.d("receiveObject::", dataState.toString())

のように記述するのだけれど、この時、呼び出し元と呼び出し先はJVM上では別のオブジェクトとして管理される。

D/sendObject::: dataState@a711d48
D/receiveObject::: dataState@225adb2

なので、呼び出し先で渡されたオブジェクトの状態を変更しても呼び出し先のオブジェクトには干渉しない。

呼び出し先で以下の操作をしても

val dataState = intent.getSerializableExtra("dataState") as DataState
dataState.data = "updated data"
finish()

呼び出し元のオブジェクトは変更されない。

this.dataState.data // "origin data"

呼び出し元に変更を伝えるには、呼び出し先でstartActivityForResult()して、呼び出し元で

dataState.data = "updated data"
val intent = Intent()
intent.putExtra("dataState", dataState)
setResult(RESULT_OK, intent)
finish()

とするしかないのかな?この時、onPause()とかライフサイクルイベントではsetResult()されない?受け取れない?みたいなので、キーイベントに応じてfinish()してあげると良さげ。以下はバックキーで呼び出し元に戻る時にオブジェクトを送信している。

override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
    if(keyCode == KeyEvent.KEYCODE_BACK){
        val intent = Intent()
        intent.putExtra("dataState", this.dataState)
        setResult(RESULT_CANCELED, intent)
        finish()
    }
    return super.onKeyDown(keyCode, event)
}