搞懂 Activity Result API (二)

403 阅读3分钟

搞懂 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);
}