Nous obtenons le bon résultat (partie 1). API de résultat d'activité

Chaque dĂ©veloppeur Android Ă©tait confrontĂ© Ă  la nĂ©cessitĂ© de transfĂ©rer des donnĂ©es d'une activitĂ© Ă  une autre. Cette tĂąche triviale nous oblige souvent Ă  Ă©crire du code moins Ă©lĂ©gant. 





Enfin, en 2020, Google a introduit une solution Ă  un ancien problĂšme: l'API Activity Result. C'est un outil puissant pour Ă©changer des donnĂ©es entre les activitĂ©s et demander des autorisations d'exĂ©cution. 





Dans cet article, nous allons comprendre comment utiliser la nouvelle API et ses avantages.





Quel est le problĂšme avec 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()



    c   PackageManager



    .





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)
           }
       }
   }
}


      
      



Mettons en pratique la connaissance de la nouvelle API et réécrivons l'écran du premier exemple avec leur aide. En conséquence, nous obtenons un code assez compact, facilement lisible et évolutif:





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?")
       }
   }
}


      
      



Nous avons vu les inconvĂ©nients de la communication via onActivityResult (), dĂ©couvert les avantages de l'API Activity Result et appris Ă  l'utiliser dans la pratique.  





La nouvelle API est complĂštement stable, alors que d'habitude onRequestPermissionsResult()



, onActivityResult()



et a startActivityForResult()



commencĂ© Ă  ĂȘtre obsolĂšte. Il est temps d'apporter des modifications Ă  vos projets! 





Une application de dĂ©monstration avec divers exemples d'utilisation de l'API Activty Result, y compris l'utilisation des autorisations d'exĂ©cution, peut ĂȘtre trouvĂ©e dans mon rĂ©fĂ©rentiel Github .








All Articles