在开发中,当在一个A的Activity中打开B的Activity界面,如果想要B->A传值的情况有很多。但是这种所有获取到的结果都需要到onActivityResult中处理的方式实在令人蛋疼。
试想一下,我们敲着代码唱着歌。突然,半路上跳出一群马匪,让我们到另一个页面获取一点数据,获取后还不让在当前代码位置处理逻辑,要去onActivityResult添加一个requestCode分支处理结果,处理完才让回来,等这一切都做完回来难免就会陷入这样的思考:我是谁,我在哪,我在干什么,我刚才写到哪了……
分析流程
A 界面需要调用如下方法:
//定义 requestCode
int mRequestCode = xxx;
context.startActivityForResult(intent, requestCode);
然后A 界面需要在onActivityResult方法中添加如下代码:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == mRequestCode){ //判断 requestCode
//执行
}
}
在 B 界面中,需要定义如下的代码:
//新界面
Intent intent = Intent()
intent.putExtra("text",text.text.toString())
setResult(Activity.RESULT_OK,intent)
finish();
这样 B->A 界面传递参数。
打开相册
比如打开相册,要写如下的代码。
private final static int REQUEST_CODE = 100;
private final static int PERMISSION_REQUEST_CODE = 200;
private void checkPermission(){
//首先进行权限判断,和请求
//先 check
//然后 requestPermissions
...
}
//当拍摄照片完成时会回调到onActivityResult 在这里处理照片的裁剪或其他的操作
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_CODE: {
//处理图片逻辑
...
break;
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
//处理权限
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//判断请求码
if(requestCode==PERMISSION_REQUEST_CODE){
if(有权限){
//在拥有权限的情况下:
Intent intentToPickPic = new Intent(Intent.ACTION_PICK, null);
// 如果限制上传到服务器的图片类型时可以直接写如:"image/jpeg 、 image/png等的类型" 所有类型则写 "image/*"
intentToPickPic.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/jpeg");
startActivityForResult(intentToPickPic, REQUEST_CODE);
}
}
}
还有一些判断等等,写起来特别麻烦。那么有没有不需要自己定义requestCode,然后不用重写onRequestPermissionsResult 和 onActivityResult 方法呢?
那么就介绍下此框架
AvoidOnResultHelper
开启 Activity
Intent intent = new Intent();
AvoidOnResultHelper.startActivityForResult(this, intent, new AvoidOnResultHelper.ActivityCallback() {
@Override
public void onActivityResult(int resultCode, Intent data) {
//处理操作
}
});
请求权限
String[] permissions = {};
AvoidOnResultHelper.requestPermissions(this, permissions, new AvoidOnResultHelper.PermissionsCallBack() {
@Override
public void onRequestPermissionsResult(@NonNull String[] permissions, @NonNull int[] grantResults) {
//处理逻辑
}
});
介绍到此处是不是感觉减少了好多代码?连requestCode 都不需要定义!~~
框架内部定义好了连requestCode,如果在开发中感觉和现有的 requestcode 冲突的话,可以设置 RequestCodeRange 范围,轻松解决问题,设置代码如下:
AvoidOnResultHelper.setRequestCodeRange(65000, 65535);
除了上面这些功能外,还有那些好用的功能?
可以监听当前 activity 的生命周期.
public interface LifecycleListener {
void onStart();//开始
void onStop();//结束
void onDestroy();//销毁
}
LifecycleListenerWrapper 是此接口的空实现.
//添加监听事件
LifecycleListener lifecycleListener = new LifecycleListener.LifecycleListenerWrapper() {
@Override
public void onStart() {
}
};
//添加监听事件
AvoidOnResultHelper.addLifecycleListener(this, lifecycleListener);
//粘性通知,当第一次添加的时候,就执行相应的回调方法
AvoidOnResultHelper.addLifecycleListener(this, lifecycleListener, true);
可选操作
//移除监听事件,默认可以不用移除lifecycleListener,除非在当前界面存在时候,想要不让某些类监听,那么可以手动进行移除(removeLifecycleListener)
AvoidOnResultHelper.removeLifecycleListener(this, lifecycleListener);
看到此处,是不是感觉不过瘾?原理讲解来了~~
原理
分析 FragmentActivity 源码
final FragmentManagerImpl mFragments = new FragmentManagerImpl();
protected void onCreate(@Nullable Bundle savedInstanceState) {
this.mFragments.attachHost((Fragment)null);
super.onCreate(savedInstanceState);
...//省略不必要的代码
this.mFragments.dispatchCreate();
}
protected void onStart() {
super.onStart();
...//省略不必要的代码
this.mFragments.noteStateNotSaved();
this.mFragments.execPendingActions();
this.mFragments.dispatchStart();
}
protected void onStop() {
super.onStop();
...//省略不必要的代码
this.mFragments.dispatchStop();
}
protected void onPause() {
super.onPause();
...//省略不必要的代码
this.mFragments.dispatchPause();
}
protected void onDestroy() {
super.onDestroy();
...//省略不必要的代码
this.mFragments.dispatchDestroy();
}
public void onLowMemory() {
super.onLowMemory();
this.mFragments.dispatchLowMemory();
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
...//省略不必要的代码
Fragment targetFragment = mFragments.findFragmentByWho(who);
targetFragment.onActivityResult(requestCode & 0xffff, resultCode, data);
...//省略不必要的代码
}
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
...//省略不必要的代码
final List<Fragment> activeFragments =
mFragments.getActiveFragments(new ArrayList<Fragment>(activeFragmentsCount));
Fragment frag = activeFragments.get(index);
if (frag == null) {
Log.w(TAG, "Activity result no fragment exists for index: 0x"
+ Integer.toHexString(requestCode));
} else {
frag.onRequestPermissionsResult(requestCode&0xff, permissions, grantResults);
}
...//省略不必要的代码
}
}
我们在来看 FragmentManagerImpl 的源码,就知道 FragmentActivity 的声明周期方法在执行的时候,都会执行包含的 fragment 的声明周期方法。代码如下:
public void dispatchCreate() {
mStateSaved = false;
moveToState(Fragment.CREATED, false);
}
public void dispatchActivityCreated() {
mStateSaved = false;
moveToState(Fragment.ACTIVITY_CREATED, false);
}
public void dispatchStart() {
mStateSaved = false;
moveToState(Fragment.STARTED, false);
}
void moveToState(int newState, boolean always) {
moveToState(newState, 0, 0, always);
}
void moveToState(int newState, int transit, int transitStyle, boolean always) {
...//省略不必要的代码
if (mActive != null) {
boolean loadersRunning = false;
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null) {
moveToState(f, newState, transit, transitStyle, false);// 执行声明周期方法
...//省略不必要的代码
}
}
...//省略不必要的代码
}
}
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
...//省略不必要的代码
switch (f.mState) {
case Fragment.INITIALIZING:
...//省略不必要的代码
f.onAttach(mActivity);
...//省略不必要的代码
if (f.mFromLayout) {
...//省略不必要的代码
if (f.mView != null) {
...//省略不必要的代码
f.onViewCreated(f.mView, f.mSavedFragmentState);
} else {
f.mInnerView = null;
}
}
case Fragment.CREATED:
...//省略不必要的代码
f.onViewCreated(f.mView, f.mSavedFragmentState);
...//省略不必要的代码
case Fragment.ACTIVITY_CREATED:
case Fragment.STOPPED:
...//省略不必要的代码
f.performStart();
case Fragment.STARTED:
...//省略不必要的代码
f.performResume();
}
} else if (f.mState > newState) {
switch (f.mState) {
case Fragment.RESUMED:
...//省略不必要的代码
f.performPause();
case Fragment.STARTED:
f.performStop();
case Fragment.STOPPED:
f.performReallyStop();
case Fragment.ACTIVITY_CREATED:
f.performDestroyView();
case Fragment.CREATED:
...//省略不必要的代码
}
}
f.mState = newState;
}
那么,我们就可以创建一个没有界面的 fragment 添加到 activity 中,就可以完美监听界面的声明周期和回调方法。到此原理讲解结束。
知识拓展
比如我们现在 很多第三方的库,glide 、Android Architecture Component 等等这些库都是使用这些原理。有兴趣的小伙伴可以立马去阅读源码~~
github地址
github: github.com/bugyun/Avoi… 欢迎star~
顺便安利下权限库:github.com/bugyun/Miss… 简单好用~