但也有一些问题…
随着应用的扩展,onActivityResult
回调方法各种嵌套、耦合严重、难以维护。 最常见的场景就是调用系统相机相册获取照片了
。代码可能像是如下这样:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
REQUEST_PERMISSION -> {
// 处理权限
}
REQUEST_CAMERA -> {
// 相机获取图片结果
}
REQUEST_ALBUM -> {
// 相册获取图片结果
}
REQUEST_CROP -> {
// 系统裁剪
}
}
}
super.onActivityResult(requestCode, resultCode, data)
}
companion object {
const val REQUEST_PERMISSION = 1001
const val REQUEST_CAMERA = 1002
const val REQUEST_ALBUM = 1003
const val REQUEST_CROP = 1004
}
}
各种处理结果都耦合在onActivityResult
回调里,并且还得定义一堆额外的常量REQUEST_CODE
,用与判断是哪个请求的回调结果。
onActivityResult 现状?
Google 可能也意识到onActivityResult
的这些问题,在androidx.activity:activity:1.2.0-alpha02
和androidx.fragment:fragment:1.3.0-alpha02
中,已经废弃了startActivityForResult
和onActivityResult
方法。
/**
- {@inheritDoc}
- @deprecated use
- {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
- passing in a {@link StartActivityForResult} object for the {@link ActivityResultContract}.
*/
@Override
@Deprecated
public void startActivityForResult(@SuppressLint(“UnknownNullness”) Intent intent,
int requestCode) {
super.startActivityForResult(intent, requestCode);
}
/**
- {@inheritDoc}
- @deprecated use
- {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
- with the appropriate {@link ActivityResultContract} and handling the result in the
- {@link ActivityResultCallback#onActivityResult(Object) callback}.
*/
@CallSuper
@Override
@Deprecated
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (!mActivityResultRegistry.dispatchResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
可以看到,这两个方法都被标记为了Deprecated
,那这两个方法不推荐使用了,Google推荐使用什么方式从Activity中更好的获取数据呢?答案就是 Activity Results API
Activity Results API
Activity Results API 是 Google官方推荐的Activity、Fragment获取数据的方式。
Activity Results API 到底怎么用?相比onActivityResult
有哪些优势?接下来,将一一为你解答。
在介绍如何使用之前,先为大家介绍Activity Results API 中两个重要的组件:ActivityResultContract
和ActivityResultLauncher
。
-
ActivityResultContract
: 协议,它定义了如何传递数据和如何处理返回的数据。ActivityResultContract
是一个抽象类,你需要继承它来创建自己的协议,每个ActivityResultContract
都需要定义输入和输出类,如果您不需要任何输入,可使用 Void(在 Kotlin 中,使用 Void? 或 Unit)作为输入类型。 -
ActivityResultLauncher
: 启动器,调用ActivityResultLauncher
的launch
方法来启动页面跳转,作用相当于原来的startActivity()
使用 Activity Results API 在Activity之间传递数据
1.
首先,在app下的build.gradle
中加入依赖:
implementation ‘androidx.activity:activity:1.2.0-beta01’
implementation ‘androidx.fragment:fragment:1.3.0-beta01’
2.
定义协议
新建一个Contract类,继承自ActivityResultContract<I,O>
,其中,I
是输入的类型,O
是输出的类型。需要实现2个方法,createIntent
和parseResult
,输入类型I
作为createIntent
的参数,输出类型O
作为parseResult
方法的返回值,在下面的例子中,输入输出类型都是String:
class MyActivityResultContract: ActivityResultContract<String,String>(){
override fun createIntent(context: Context, input: String?): Intent {
return Intent(context,SecondActivity::class.java).apply {
putExtra(“name”,input)
}
}
override fun parseResult(resultCode: Int, intent: Intent?): String? {
val data = intent?.getStringExtra(“result”)
return if (resultCode == Activity.RESULT_OK && data != null) data
else null
}
}
如上代码,我们在createIntent
方法中创建了Intent,并且携带了参数name
,在parseResult
方法中,获取了返回的数据result
。
3.
注册协议,获取启动器-ActivityResultLauncher
注册协议,使用registerForActivityResult
方法,该方法由ComponentActivity
或者Fragment
提供,接受2个参数,第一个参数就是我们定义的Contract协议,第二个参数是一个回调ActivityResultCallback<O>
,其中O
就是前面Contract的输出类型。代码如下:
private val myActivityLauncher = registerForActivityResult(MyActivityResultContract()){result ->
Toast.makeText(applicationContext,result,Toast.LENGTH_SHORT).show()
textView.text = “回传数据:$result”
}
如上代码,注册了MyActivityResultContract
,registerForActivityResult
方法的返回值是ActivityResultLauncher
, 因此我们定义了一个myActivityLauncher
,回调方法中,result
就是从上一个界面传回的值。这里我们简单的用Toast显示。
4.
最后,调用启动器的launch方法开启界面跳转
MainActivity
中添加一个Button,点击Button时,调用launch
方法跳转:
button.setOnClickListener {
// 开启页面跳转
myActivityLauncher.launch(“Hello,技术最TOP”)
}
SecondActivity
的代码很简单:
class SecondActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.second_layout)
val name = intent.getStringExtra(“name”)
textView3.text = “接收到的数据为:$name”
button2.setOnClickListener {
val intent = Intent().apply {
putExtra(“result”,“Hello,依然范特西稀,我是回传的数据!”)
}
setResult(Activity.RESULT_OK,intent)
finish()
}
}
}
以上3步,就实现了使用新的Activity Results API
来完成Activity之间的数据传递,并获取Activity返回的数据
看一下效果:
这就完了吗?
你可能会有疑问,虽然确实减少了代码耦合,但是使用并不简单啊。
确实,但这并没有完!!!
预定义的Contract
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
文末
面试:如果不准备充分的面试,完全是浪费时间,更是对自己的不负责!
不管怎么样,不论是什么样的大小面试,要想不被面试官虐的不要不要的,只有刷爆面试题题做好全面的准备,当然除了这个还需要在平时把自己的基础打扎实,这样不论面试官怎么样一个知识点里往死里凿,你也能应付如流啊
204888 (备注Android)**
[外链图片转存中…(img-g07kjFyo-1711827401338)]
文末
面试:如果不准备充分的面试,完全是浪费时间,更是对自己的不负责!
不管怎么样,不论是什么样的大小面试,要想不被面试官虐的不要不要的,只有刷爆面试题题做好全面的准备,当然除了这个还需要在平时把自己的基础打扎实,这样不论面试官怎么样一个知识点里往死里凿,你也能应付如流啊