Androidアプリ開発入門:画面遷移を実装する

AndroidのアプリをAndroid Studioで作っています。今回は画面遷移を実装してみようと思いました。画面遷移はActivityの遷移で発生し、遷移自体はIntentを使って実現できます。ただ、Activityの前後でデータをやり取りしようとすると一つ処理を挟む必要が出てきます。それがstartActivityForResultです。

実際に書いてみました。

おっと、なぜか取り消し線が引かれてしまいました。どういうことかとクリックしてみると

Deprecate(非推奨)となっていました。実際、2020年の2月には既に新しい方法が提示されていたそうです。
では何を使うのかというと、ActivityResultLauncher です。
こんな感じで変数を定義し、

val startforRes = registerForActivityResult(ActivityResultContracts.StartActivityForResult())
{
        result ->
    if (result.resultCode != RESULT_OK){}
    val resstr = result.data?.getStringExtra(act1.ResultExtr.MESSAGE.name)
    binding.textview.text = resstr
}
startforRes.launch(intent)

で遷移させます。
これをビルドするとこんなエラーが。

java.lang.IllegalStateException: LifecycleOwner com.example.mytrial.MainActivity@61d557e is attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.

どうやら、ライフサイクルにおいて、Startedする前に定義しないといけないみたいです。実際、onCreateの中で定義していたものを、次のように外出しすることでエラーを回避しました。

 val startforRes = registerForActivityResult(ActivityResultContracts.StartActivityForResult())
    {
            result ->
        if (result.resultCode != RESULT_OK){}
        val resstr = result.data?.getStringExtra(act1.ResultExtr.MESSAGE.name)
        binding.textview.text = resstr
    }

    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        var counter = 0
        setContentView(binding.root)

        val rootLayout: View = findViewById(android.R.id.content)

        val snackbar = Snackbar.make(rootLayout , "Snackbar message", Snackbar.LENGTH_LONG)
        snackbar.setAction("Touch me"){
            binding.textview.text = "You touched!"
        }
        snackbar.show()

        binding.button1.setOnClickListener{
            counter++
            binding.textview.text = counter.toString()

            val snackbar2 = Snackbar.make(rootLayout , counter.toString(), Snackbar.LENGTH_LONG)
                .setAction("Undo") {
                    counter--
                    binding.textview.text = "Minused $counter"
                }.show()
        }

        binding.button2.setOnClickListener{
            val intent = Intent(applicationContext, act1::class.java)
            val str = binding.editText1.text
            intent.putExtra(MY_MSG, binding.editText1.text.toString())
            startforRes.launch(intent)

        }
    }
}

アクティビティの遷移前後でデータをやり取りする箇所が、putExtra(MY_MSG, binding.editText1.text.toString())
です。このコードのうち、最後のtoString()をつけ忘れるとString型でデータが送られないため、受取先で文字が表示できませんでした。

ちなみに、受取先のコードはこちら。

private lateinit var binding: ActivityAct1Binding

class act1 : AppCompatActivity() {
    enum class ResultExtr {
        MESSAGE
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityAct1Binding.inflate(layoutInflater)
        setContentView(binding.root)
        val getstr = intent.getStringExtra(MainActivity.MY_MSG)
        binding.textView21.text = getstr

        binding.button.setOnClickListener{
            finishActivity()
        }
    }
    fun finishActivity(){
        val intent = Intent().apply {
            putExtra(ResultExtr.MESSAGE.name, "hei")
        }
        setResult(RESULT_OK, intent)
        finish()
    }
}

遷移先から遷移元にデータを渡すには、 Intent().apply { putExtra(ResultExtr.MESSAGE.name, "hei") } のようにapplyの中でputExtraを呼びます。



この記事が気に入ったらサポートをしてみませんか?