Setiap pengembang Android menghadapi kebutuhan untuk mentransfer data dari satu Aktivitas ke aktivitas lainnya. Tugas sepele ini sering kali memaksa kita untuk menulis kode yang kurang elegan.
Terakhir, pada tahun 2020, Google memperkenalkan solusi untuk masalah lama - API Hasil Aktivitas. Ini adalah alat yang ampuh untuk bertukar data antara aktivitas dan meminta izin waktu proses.
Pada artikel ini, kami akan memahami cara menggunakan API baru dan keuntungan apa yang dimilikinya.
Apa yang salah dengan onActivityResult ()?
β β β DRY Donβt repeat yourself, , .
onActivityResult()
, . , , β SecondActivity
. SecondActivity
, .
class OldActivity : AppCompatActivity(R.layout.a_main) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
vButtonCamera.setOnClickListener {
when {
checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED -> {
// ,
startActivityForResult(
Intent(MediaStore.ACTION_IMAGE_CAPTURE),
PHOTO_REQUEST_CODE
)
}
shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
// ,
}
else -> {
// ,
requestPermissions(
arrayOf(Manifest.permission.CAMERA),
PHOTO_PERMISSIONS_REQUEST_CODE
)
}
}
}
vButtonSecondActivity.setOnClickListener {
val intent = Intent(this, SecondActivity::class.java)
.putExtra("my_input_key", "What is the answer?")
startActivityForResult(intent, SECOND_ACTIVITY_REQUEST_CODE)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
PHOTO_REQUEST_CODE -> {
if (resultCode == RESULT_OK && data != null) {
val bitmap = data.extras?.get("data") as Bitmap
// bitmap
} else {
//
}
}
SECOND_ACTIVITY_REQUEST_CODE -> {
if (resultCode == RESULT_OK && data != null) {
val result = data.getIntExtra("my_result_extra")
// result
} else {
//
}
}
else -> super.onActivityResult(requestCode, resultCode, data)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == PHOTO_PERMISSIONS_REQUEST_CODE) {
when {
grantResults[0] == PackageManager.PERMISSION_GRANTED -> {
// ,
startActivityForResult(
Intent(MediaStore.ACTION_IMAGE_CAPTURE),
PHOTO_REQUEST_CODE
)
}
!shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
// , Don't ask again.
}
else -> {
// ,
}
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
}
companion object {
private const val PHOTO_REQUEST_CODE = 1
private const val PHOTO_PERMISSIONS_REQUEST_CODE = 2
private const val SECOND_ACTIVITY_REQUEST_CODE = 3
}
}
, onActivityResult()
, Activity. , .
, , .
Activity Result API
API AndroidX Activity 1.2.0-alpha02
Fragment 1.3.0-alpha02
, build.gradle:
implementation 'androidx.activity:activity-ktx:1.3.0-alpha02'
implementation 'androidx.fragment:fragment-ktx:1.3.0'
Activity Result :
1.
β , ActivityResultContract<I,O>.
I
, Activity, O
β .
β β: PickContact
, TakePicture
, RequestPermission
. .
:
createIntent()
β , launch()
parseResult()
β , resultCode
β getSynchronousResult()
β . , Activity, , , . , null
.
, SecondActivity, :
class MySecondActivityContract : ActivityResultContract<String, Int?>() {
override fun createIntent(context: Context, input: String?): Intent {
return Intent(context, SecondActivity::class.java)
.putExtra("my_input_key", input)
}
override fun parseResult(resultCode: Int, intent: Intent?): Int? = when {
resultCode != Activity.RESULT_OK -> null
else -> intent?.getIntExtra("my_result_key", 42)
}
override fun getSynchronousResult(context: Context, input: String?): SynchronousResult<Int?>? {
return if (input.isNullOrEmpty()) SynchronousResult(42) else null
}
}
2.
β registerForActivityResult()
. ActivityResultContract
ActivityResultCallback
. .
val activityLauncher = registerForActivityResult(MySecondActivityContract()) { result ->
// result
}
Activity
, ActivityResultLauncher
, .
3.
Activity launch()
ActivityResultLauncher
, .
vButton.setOnClickListener {
activityLauncher.launch("What is the answer?")
}
!
, :
, CREATED . β .
registerForActivityResult()
if
when
. , (, , ). , .
, Activity, ActivityNotFoundException: βNo Activity found to handle Intentβ. ,
launch()
getSynchronousResult()
resolveActivity()
cPackageManager
.
runtime permissions
Activity Result API . checkSelfPermission()
, requestPermissions()
onRequestPermissionsResult()
, β RequestPermission
RequestMultiplePermissions
.
, β . RequestPermission
true
, , false
. RequestMultiplePermissions
Map
, β , β .
. Google :
runtime permissions:
, , ( 5a)
( 8b), , , βDon't ask againβ
shouldShowRequestPermissionRationale()
. true
, , . shouldShowRequestPermissionRationale()
false
β βDon't ask againβ, .
:
class PermissionsActivity : AppCompatActivity(R.layout.a_main) {
val singlePermission = registerForActivityResult(RequestPermission()) { granted ->
when {
granted -> {
// ,
}
!shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
// , Don't ask again.
}
else -> {
// ,
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
vButtonPermission.setOnClickListener {
if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
// ,
} else {
singlePermission.launch(Manifest.permission.CAMERA)
}
}
}
}
Mari kita praktikkan pengetahuan tentang API baru dan tulis ulang layar dari contoh pertama dengan bantuan mereka. Hasilnya, kami mendapatkan kode yang cukup ringkas, mudah dibaca, dan dapat diskalakan:
class NewActivity : AppCompatActivity(R.layout.a_main) {
val permission = registerForActivityResult(RequestPermission()) { granted ->
when {
granted -> {
camera.launch() // ,
}
!shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
// , Don't ask again.
}
else -> {
//
}
}
}
val camera = registerForActivityResult(TakePicturePreview()) { bitmap ->
// bitmap
}
val custom = registerForActivityResult(MySecondActivityContract()) { result ->
// result
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
vButtonCamera.setOnClickListener {
if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
// ,
} else {
permission.launch(Manifest.permission.CAMERA)
}
}
vButtonSecondActivity.setOnClickListener {
custom.launch("What is the answer?")
}
}
}
Kami melihat kerugian berkomunikasi melalui onActivityResult (), mempelajari tentang keuntungan API Hasil Aktivitas, dan mempelajari cara menggunakannya dalam praktik.
API baru benar-benar stabil, seperti biasa onRequestPermissionsResult()
, onActivityResult()
dan startActivityForResult()
mulai Deprecated. Saatnya membuat perubahan pada proyek Anda!
Aplikasi demo dengan berbagai contoh penggunaan API Hasil Aktivasi, termasuk bekerja dengan izin waktu proses, dapat ditemukan di repositori Github saya .