【SmartAndroid之SmartJump,告别onActivityResult】
SmartJump
- 需求
- 应用场景
- 实现思路
- 代码
- 调用示例
- 后记
需求 在跳转到另一个Activity后,通过回调直接获取到数据
应用场景
- 普通的activity跳转,回调获取数据可以使逻辑更清晰
- 第三方库中activity数据回调可以让使用者调用起来更方便
- 其实一开始并没有思路。我自己的一个图片选择框架也实现了图片回调,不需要从onActivityResult中获取。但是我用的方式是在跳转activity前建立一个RxBus监听,在获取到图片数据后,用RxBus把数据发送回来,在RxBus里接收并通过传入的回调函数将值返回。用法是没问题的,但是要多引一个rxjava包,而且实现的思路有点绕。
- 有一天,我在对比几个permission请求库的优劣的时候发现,RxPermission有个很棒的优点,不需要重写onPermissionsGranted,很是神奇。因为RxPermission代码比较少,很快我就搞明白了大佬是怎么实现的。大佬在请求权限的时候先启动了一个fragment,然后在fragment里请求权限,又在fragment的onRequestPermissionsResult中把请求结果回调。这就是传说中的代理模式嘛?大佬真的厉害,Or2。既然请求权限可以这么搞,那么跳转回调也就是一样的道理了。于是,我照着大神的代码,怼了怼,搞出了新的跳转库,很简单就一个类
public class SmartJump {private static final String TAG = BuildConfig.APPLICATION_ID + SmartJump.class.getSimpleName();
private ResultBridgeFragment resultBridgeFragment;
public static SmartJump from(@NonNull FragmentActivity activity) {
return new SmartJump(activity.getSupportFragmentManager());
}public static SmartJump from(@NonNull Fragment fragment) {
return new SmartJump(fragment.getChildFragmentManager());
}public static SmartJump with(@NonNull FragmentManager fragmentManager) {
return new SmartJump(fragmentManager);
}@SuppressWarnings("WeakerAccess")
public void startForResult(Intent intent, Callback callback) {
resultBridgeFragment.startForResult(intent, callback);
}public void startForResult(Class> clazz, Callback callback) {
Intent intent = new Intent(resultBridgeFragment.getActivity(), clazz);
startForResult(intent, callback);
}public interface Callback {
/**
* 回调
*
* @param resultCode code
* @param datadata
*/
void onActivityResult(int resultCode, Intent data);
}private SmartJump(FragmentManager fragmentManager) {
resultBridgeFragment = getResultBridgeFragment(fragmentManager);
}private ResultBridgeFragment getResultBridgeFragment(@NonNull final FragmentManager fragmentManager) {
ResultBridgeFragment bridgeFragment = (ResultBridgeFragment)fragmentManager.findFragmentByTag(TAG);
// 假如fragment 已经添加过了就不用重复添加了
if (bridgeFragment == null) {
bridgeFragment = new ResultBridgeFragment();
fragmentManager
.beginTransaction()
.add(bridgeFragment, TAG)
.commitNow();
}
return bridgeFragment;
}publicstatic class ResultBridgeFragment extends Fragment {
private SparseArray mCallbacks = new SparseArray<>();
/**
* 每次启动都会有个不同的requestCode
* 因为某个activity可能会多个跳转回调
*/
private int uniqueCode = 1;
public ResultBridgeFragment() {
}@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设备旋转 数据保留
setRetainInstance(true);
}/**
* 防止 同时多个activity启动 造成request相同
*
* @param intentintent
* @param callback 回调
*/
public synchronized void startForResult(Intent intent, Callback callback) {
// 保证requestCode 每个都不同
uniqueCode++;
mCallbacks.put(uniqueCode, callback);
startActivityForResult(intent, uniqueCode);
}@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Callback callback = mCallbacks.get(requestCode);
if (callback != null) {
callback.onActivityResult(resultCode, data);
}
mCallbacks.remove(requestCode);
}
}
}
调用示例
SmartJump.from(this).startForResult(TestBackActivity.class, new SmartJump.Callback() {
@Override
public void onActivityResult(int resultCode, Intent data) {
ToastUtils.showMessage("jump_a backButton" + resultCode);
}
});
后记
- 使用一个空fragment作为Activity的代理,非常的机智。你可以发现liveData中的ViewModelStores也用到了这个骚操作,有兴趣的同学可以看看。
- 有一个遗憾,因为实现方式是借用了一个fragment,而fragment又分为v4下和app下的,本来想兼容一下,但是代码就变得很啰嗦很奇怪。鉴于大部分开发者和谷歌推荐是用v4下fragment,所以就只支持v4fragment。因而,调用SmartJump的页面需要继承fragmentActivity (AppCompatActivity就阔以) 或者v4的fragment。
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Spring注解驱动第十讲--@Autowired使用
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验
- jvm|【JVM】JVM08(java内存模型解析[JMM])
- 技术|为参加2021年蓝桥杯Java软件开发大学B组细心整理常见基础知识、搜索和常用算法解析例题(持续更新...)