搞懂 Activity Result API (二)
「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」
延伸一:RequestCode 如何生成
在启动 Activity 的时候,RequestCode 都是唯一的。那如何保证其唯一性呢?且看下面分析:
1、指定唯一的字符串
先给每个启动 Activity 都指定一个 唯一的字符串:
private final AtomicInteger mNextLocalRequestCode = new AtomicInteger();
// 字符串 key 值
"activity_rq#" + mNextLocalRequestCode.getAndIncrement()
2、给唯一的字符串生成唯一的随机数
对每个 key 生成一个随机数:
final int requestCode = registerKey(key);
// 这个 map 是 根据 key, 来查询是否有生成过 int 值
private final Map<String, Integer> mKeyToRc = new HashMap<>();
private int registerKey(String key) {
Integer existing = mKeyToRc.get(key);
if (existing != null) {
return existing;
}
int rc = generateRandomNumber();
bindRcKey(rc, key);
return rc;
}
// Use upper 16 bits for request codes
private static final int INITIAL_REQUEST_CODE_VALUE = 0x00010000;
private Random mRandom = new Random();
// 这个 map 是用来保证没有重复的 int 值
private final Map<Integer, String> mRcToKey = new HashMap<>();
private int generateRandomNumber() {
int number = mRandom.nextInt((Integer.MAX_VALUE - INITIAL_REQUEST_CODE_VALUE) + 1)
+ INITIAL_REQUEST_CODE_VALUE;
while (mRcToKey.containsKey(number)) {
number = mRandom.nextInt((Integer.MAX_VALUE - INITIAL_REQUEST_CODE_VALUE) + 1)
+ INITIAL_REQUEST_CODE_VALUE;
}
return number;
}
// 互相绑定
private void bindRcKey(int rc, String key) {
mRcToKey.put(rc, key);
mKeyToRc.put(key, rc);
}
延伸二:ActivityResult 实现 Parcelable 序列化
ActivityResult 通过实现 Parcelable 接口来实现序列化。如下:
1、ActivityResult 的实现
public final class ActivityResult implements Parcelable {
private final int mResultCode;
@Nullable
private final Intent mData;
/**
* Create a new instance
*
* @param resultCode status to indicate the success of the operation
* @param data an intent that carries the result data
*/
public ActivityResult(int resultCode, @Nullable Intent data) {
mResultCode = resultCode;
mData = data;
}
// 反序列化功能由 CREATOR 来完成,其内部标明了如何创建序列化对象 和 数组,并通过 Parcel 的一系列 read 方法来完成反序列化过程。
ActivityResult(Parcel in) {
mResultCode = in.readInt();
mData = in.readInt() == 0 ? null : Intent.CREATOR.createFromParcel(in);
}
/**
* @return the resultCode
*/
public int getResultCode() {
return mResultCode;
}
/**
* @return the intent
*/
@Nullable
public Intent getData() {
return mData;
}
@Override
public String toString() {
return "ActivityResult{"
+ "resultCode=" + resultCodeToString(mResultCode)
+ ", data=" + mData
+ '}';
}
/**
* A readable representation of standard activity result codes
*
* @param resultCode the result code
*
* @return RESULT_OK, RESULT_CANCELED, or the number otherwise
*/
@NonNull
public static String resultCodeToString(int resultCode) {
switch (resultCode) {
case Activity.RESULT_OK: return "RESULT_OK";
case Activity.RESULT_CANCELED: return "RESULT_CANCELED";
default: return String.valueOf(resultCode);
}
}
// 序列化功能由 writeToParcel 方法完成,最终是通过 Parcel 中的一系列 write 方法来完成的
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mResultCode);
dest.writeInt(mData == null ? 0 : 1);
if (mData != null) {
mData.writeToParcel(dest, flags);
}
}
// 内容描述符
@Override
public int describeContents() {
return 0;
}
@NonNull
public static final Creator<ActivityResult> CREATOR = new Creator<ActivityResult>() {
// 从序列化后的对象中创建原始对象
@Override
public ActivityResult createFromParcel(@NonNull Parcel in) {
return new ActivityResult(in);
}
// 创建指定长度的原始对象数组
@Override
public ActivityResult[] newArray(int size) {
return new ActivityResult[size];
}
};
}
2、实现 Parcelbale 的注意点
所以,实现 Parcelable ,要实现以下几个方法:
- 序列化功能:
writeToParcel
// 序列化功能由 writeToParcel 方法完成,最终是通过 Parcel 中的一系列 write 方法来完成的
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mResultCode);
dest.writeInt(mData == null ? 0 : 1);
if (mData != null) {
mData.writeToParcel(dest, flags);
}
}
- 内容描述符:
describeContents
// 内容描述符
@Override
public int describeContents() {
return 0;
}
- 反序列化:
// 反序列化功能由 CREATOR 来完成,其内部标明了如何创建序列化对象 和 数组,并通过 Parcel 的一系列 read 方法来完成反序列化过程。
ActivityResult(Parcel in) {
mResultCode = in.readInt();
mData = in.readInt() == 0 ? null : Intent.CREATOR.createFromParcel(in);
}
@NonNull
public static final Creator<ActivityResult> CREATOR = new Creator<ActivityResult>() {
// 从序列化后的对象中创建原始对象
@Override
public ActivityResult createFromParcel(@NonNull Parcel in) {
return new ActivityResult(in);
}
// 创建指定长度的原始对象数组
@Override
public ActivityResult[] newArray(int size) {
return new ActivityResult[size];
}
};
延伸三: Activtiy Result API 使用 Lifecycle
我们可以放心大胆地使用 Activity Result API,而不用担心是否需要回收资源的事情,因为这里已经引入了 Lifecycle ,在页面 onDestory 的时候会自动调用 unregister 方法。
1、传入 LifecycleOwner 对象
ComponentActivity 类是实现了 LifecycleOwner 接口,并在 register 方法中传入了 LifecycleOwner 对象
// ComponentActivity.java
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
ContextAware,
LifecycleOwner {
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
@NonNull final ActivityResultContract<I, O> contract,
@NonNull final ActivityResultRegistry registry,
@NonNull final ActivityResultCallback<O> callback) {
// this -> 是 LifecycleOwner 对象
return registry.register(
"activity_rq#" + mNextLocalRequestCode.getAndIncrement(), this, contract, callback);
}
}
2、处理 Lifecycle 对象逻辑
在 ActivityResultRegistry 类中的 register 方法体现生命周期:
public final <I, O> ActivityResultLauncher<I> register(
@NonNull final String key,
@NonNull final LifecycleOwner lifecycleOwner,
@NonNull final ActivityResultContract<I, O> contract,
@NonNull final ActivityResultCallback<O> callback) {
Lifecycle lifecycle = lifecycleOwner.getLifecycle();
if (lifecycle.getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
throw new IllegalStateException("...");
}
LifecycleContainer lifecycleContainer = mKeyToLifecycleContainers.get(key);
if (lifecycleContainer == null) {
lifecycleContainer = new LifecycleContainer(lifecycle);
}
LifecycleEventObserver observer = new LifecycleEventObserver() {
@Override
public void onStateChanged(
@NonNull LifecycleOwner lifecycleOwner,
@NonNull Lifecycle.Event event) {
if (Lifecycle.Event.ON_START.equals(event)) {
//...
} else if (Lifecycle.Event.ON_STOP.equals(event)) {
mKeyToCallback.remove(key);
} else if (Lifecycle.Event.ON_DESTROY.equals(event)) {
unregister(key);
}
}
};
lifecycleContainer.addObserver(observer);
}
3、自定义静态类存储 Lifecycle
我们可以看到上面代码是绑定了生命周期,这里有一个内部类 LifecycleContainer,它的实现如下:
private static class LifecycleContainer {
final Lifecycle mLifecycle;
private final ArrayList<LifecycleEventObserver> mObservers;
LifecycleContainer(@NonNull Lifecycle lifecycle) {
mLifecycle = lifecycle;
mObservers = new ArrayList<>();
}
void addObserver(@NonNull LifecycleEventObserver observer) {
mLifecycle.addObserver(observer);
mObservers.add(observer);
}
void clearObservers() {
for (LifecycleEventObserver observer: mObservers) {
mLifecycle.removeObserver(observer);
}
mObservers.clear();
}
}
延伸四 泛型的使用
1、泛型方法
ComponentActivity 中使用泛型方法:
public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
@NonNull ActivityResultContract<I, O> contract,
@NonNull ActivityResultCallback<O> callback) {
return registerForActivityResult(contract, mActivityResultRegistry, callback);
}
@NonNull
@Override
public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
@NonNull final ActivityResultContract<I, O> contract,
@NonNull final ActivityResultRegistry registry,
@NonNull final ActivityResultCallback<O> callback) {
return registry.register(
"activity_rq#" + mNextLocalRequestCode.getAndIncrement(), this, contract, callback);
}
private final ActivityResultRegistry mActivityResultRegistry = new ActivityResultRegistry() {
@Override
public <I, O> void onLaunch(
final int requestCode,
@NonNull ActivityResultContract<I, O> contract,
I input,
@Nullable ActivityOptionsCompat options) {
...
}
}
ActivityResultRegistry 中使用泛型方法:
public final <I, O> ActivityResultLauncher<I> register(
@NonNull final String key,
@NonNull final ActivityResultContract<I, O> contract,
@NonNull final ActivityResultCallback<O> callback) {
return new ActivityResultLauncher<I>() {
@Override
public void launch(I input, @Nullable ActivityOptionsCompat options) {
mLaunchedKeys.add(key);
onLaunch(requestCode, contract, input, options);
}
@NonNull
@Override
public ActivityResultContract<I, ?> getContract() {
return contract;
}
};
}
@MainThread
public abstract <I, O> void onLaunch(
int requestCode,
@NonNull ActivityResultContract<I, O> contract,
@SuppressLint("UnknownNullness") I input,
@Nullable ActivityOptionsCompat options);
private <O> void doDispatch(String key, int resultCode, @Nullable Intent data, CallbackAndContract<O> callbackAndContract) {
...
}
2、泛型类
ActivityResultLauncher泛型类:
public abstract class ActivityResultLauncher<I> {
public void launch(@SuppressLint("UnknownNullness") I input) {
launch(input, null);
}
...
}
ActivityResultCallback 泛型类:
public interface ActivityResultCallback<O> {
/**
* Called when result is available
*/
void onActivityResult(@SuppressLint("UnknownNullness") O result);
}
ActivityResultContract 泛型类:
public abstract class ActivityResultContract<I, O> {
public abstract @NonNull Intent createIntent(@NonNull Context context, @SuppressLint("UnknownNullness") I input);
public abstract O parseResult(int resultCode, @Nullable Intent intent);
}