728x90
기존에 사용하던 startActivityForResult() & onActivityResult() 를 대체하는 새로운 Activity Result API 가 나왔다.
기존 API 의 단점
- 강한 결합으로 코드를 다른 곳으로 분리시킬 수 없다.
- 개발자의 부주의로 casting error 가 발생할 수 있다.
- null pointer exception 역시 발생하기 쉬운 구조다.
새로운 API 의 장점
- 원하는 Activity Request마다 registerForActivityResult를 실행하기 때문에 requestCode가 존재하지 않는다.
- onActivityResult 를 override 할 필요가 없으므로 boilerplate code 가 줄어든다.
- 하나의 launcher 는 하나의 contract 를 실행하고 그 결과를 하나의 callback 으로 반환한다.
사용 방법
액티비티에서 registerForActivityResult 함수를 사용해서 Callback을 등록해준다.
인자로는 ActivityResultContracts 클래스의 Static 함수들을 넣어준다.
Result를 받기위해서 Activity를 실행하는 StartActivityForResult() 등의 함수를 넣어준다.
람다식에는 result로 받아온 값을 어떻게 사용하는지 정의해준다.
인자로 받아온 result객체를 이용하면, resultCode와 data에 접근할 수 있다.
위에서 정의한 내용을 launch 함수로 실행시켜 주면 된다.
코드
(java)
private ActivityResultLauncher<Intent> ContractStartActivityResult =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
final String strInput = result.getData().getStringExtra(Constant.RESULT_INPUT);
((TextView) findViewById(R.id.input)).setText(strInput);
}
}
});
ContractStartActivityResult.launch(intent)
(kotlin)
activityLauncher = activity.registerForActivityResult(
ActivityResultContracts.StartIntentSenderForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
// something..
}
it.onComplete()
}
val pendingIntent = MediaStore.createDeleteRequest(resolver, uriList)
activityLauncher.launch(
IntentSenderRequest.Builder(pendingIntent.intentSender).build()
)
ActivityResultContracts 에는 미리 빌드된 ActivityResultContract 클래스가 여러 개 포함되어 사용할 수 있다.
또한, 개발자가 필요한 유형의 Custom Contracts 를 직접 만들 수도 있다.
(java)
public class MainContract extends ActivityResultContract<String, String> {
@Override
public Intent createIntent(Context context, String strSendText) {
Intent intent = new Intent(context, SubActivity.class);
intent.putExtra(Constant.SEND_TEXT, strSendText);
return intent;
}
@Override
public String parseResult(int resultCode, Intent intent) {
if (resultCode == Activity.RESULT_OK) {
if (intent != null) {
return intent.getStringExtra(Constant.RESULT_INPUT);
}
}
return "";
}
}
// Custom contract
private ActivityResultLauncher<String> CustomContractStartActivityResult =
registerForActivityResult(
new MainContract(),
new ActivityResultCallback<String>() {
@Override
public void onActivityResult(String strResult) {
((TextView) findViewById(R.id.input)).setText(strResult);
}
}
);
CustomContractStartActivityResult.launch("hi");
(kotlin)
class MainContract : ActivityResultContract<String, String>() {
override fun createIntent(a_context: Context, strSendText: String): Intent {
return Intent(context, SubActivity::class.java).apply {
putExtra(Constant.SEND_TEXT, strSendText)
}
}
override fun parseResult(resultCode: Int, intent: Intent?): String? =
if (resultCode == Activity.RESULT_OK) intent?.getStringExtra(MainActivity.Constant.RESULT_INPUT)
else ""
}
// Custom contract
private val customContractStartActivityResult =
registerForActivityResult(MainContract()) { result ->
result?.let {
input.text = it
}
}
customContractStartActivityResult.launch("hi")
'Kotlin > 안드로이드 공부' 카테고리의 다른 글
안드로이드12 Splash Screen (0) | 2023.01.12 |
---|---|
Hilt @Provides vs @Binds (0) | 2022.06.10 |
외부 앱에 공유하기 이슈 (w.안드로이드 11 패키지 공개 상태) (0) | 2022.01.03 |
Spans - 문자열 중 숫자에만 텍스트 효과 적용하기 (0) | 2021.10.21 |
Rxjava Single 안의 값 사용하기 (0) | 2021.10.19 |