本文主要讲解Activity的onActivityResult的问题。
记得刚开始开发项目的时候需求一下来时,噼里啪啦直接敲代码,功能实现是没问题了,后期其它同事维护时发现代码非常臃肿,特别当需要修改或添加功能时,涉及到一些特别庞大的对象,立马懵逼了。
页面之间交互、startActivityForResult跳转到系统指定页面 这些是在项目里非常常用的,当页面功能越庞大,那么它的请求和响应也对应的越臃肿,面对一大堆代码时,就会出现在onActivityResult方法里忘记刚刚写的请求码是多少,又得回头看一眼还担心出错的问题,看着onActivityResult里面的各种 if() else if(),连自己都懵逼了。
废话不多说了,思路是通过一个无视图的Frgament对象作为桥梁,使用它进行请求和响应来避免我们自己的onActivityResult方法等,封装一个BridegResult类,构造BridegResult时创建一个无视图的BridegFragment对象,与Activity绑定生命周期方便同步一些逻辑处理,所有的具体逻辑封装在BridegFragment类里,传递接口进行回调,BridegResult只提供一些调用方法。
本文提供的代码是根据我自己的项目需求封装而成,对权限和数据传递两个部分做了一个封装,只是提供思路供大家参考,如有错误之处请指正!
注释很清晰,代码如下!
public class BridegResult{
private BridegFragment mBridegFragment;
private String mTag = "tag";
public BridegResult(FragmentActivity activity){
mBridegFragment = getBridegFragment(activity);
}
public BridegResult(Fragment fragment){
mBridegFragment = getBridegFragment(fragment.getActivity());
}
//初始化Frgament对象 进行生命周期绑定
private BridegFragment getBridegFragment(FragmentActivity activity){
//初始化Fragment时,将它与Activity生命周期进行绑定
BridegFragment bridegFragment = new BridegFragment();
FragmentManager manager = activity.getSupportFragmentManager();
manager.beginTransaction().add(bridegFragment,mTag).commitAllowingStateLoss();
return bridegFragment;
}
//提供跳转方法
public void startResult(Intent intent, int requestCode, CallbackResult callback){
mBridegFragment.startResult(intent,requestCode,callback);
}
//提供授权方法
public void requestPermissions(String[] permissions, int requestCode,String content, CallbackPermissi callback) {
mBridegFragment.requestPermissions(permissions,requestCode,content,callback);
}
}
具体逻辑如下:
public class BridegFragment extends Fragment { private Map<Integer,CallbackResult> mCallbackMap = new HashMap<>(); //结果集合 private Map<Integer,CallbackPermissi> mCallbackPermissionsMap = new HashMap<>(); //权限集合 private PopUpWindowPermission mPopUpWindowPermission; //提示窗口 private static final int PERMISSIONS_FLAG = 88; //授权标识 private int mCurrentCode; private String[] mCurrentPermissions; private String mHintContent; @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode == PERMISSIONS_FLAG){ //这是权限回调 CallbackPermissi callbacks = mCallbackPermissionsMap.remove(mCurrentCode); if(null != callbacks){ //假设用户跳转到系统授权页面,不授权返回,也会执行当前方法,需要二次判断权限 //mCurrentPermissions mCurrentCode 就是记录当前的权限 if(Utils.isPermission(getContext(),mCurrentPermissions)){ callbacks.onPermissionSucceed(mCurrentCode); }else{ callbacks.onPermissionFailed(mCurrentCode); } } }else{ //这是普通的数据回调 CallbackResult callback = mCallbackMap.remove(requestCode); if(null != callback){ callback.onActivityResult(requestCode,resultCode,data); } } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); //用户同意权限 if(isPermission(grantResults)){ CallbackPermissi callback = mCallbackPermissionsMap.remove(requestCode); if(null != callback){ callback.onPermissionSucceed(requestCode); } }else { //用户勾选 不在询问,我们再次请求权限时,会被系统直接默认到当前方法的失败状态,所以要针对性处理这个问题 //勾选就弹出窗口帮助用户自动跳转到系统授权页面 if(isPermissionRationale(getActivity(),permissions)){ showWindow(); }else{ //没有勾选就提示用户需要授权 CallbackPermissi callback = mCallbackPermissionsMap.remove(requestCode); if(null != callback){ callback.onPermissionFailed(requestCode); } } }} //判断用户是否设置了某个权限为 不在询问 private boolean isPermissionRationale(FragmentActivity activitie,String[] permissions){ boolean flag = false; for (int i=0;i<permissions.length;i++){ if(!ActivityCompat.shouldShowRequestPermissionRationale(activitie,permissions[i])) { flag = true; break; } } return flag; } //判断用户是否全部授权了 正常一组权限当中第0个授权,其它默认授权,考虑到调用者传的权限数组不止一组,需要都进行判断 private boolean isPermission(int[] grantResults){ boolean flag = true; for (int i=0;i<grantResults.length;i++){ if(grantResults[i] != PackageManager.PERMISSION_GRANTED){ flag = false; break; } } return flag; } //跳转到页面的授权页面 private void showWindow() { if (null == mPopUpWindowPermission) { mPopUpWindowPermission = new PopUpWindowPermission(getActivity(), new PopUpWindowPermission.OnClick() { @Override public void config() { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getContext().getPackageName(), null); intent.setData(uri); startActivityForResult(intent, PERMISSIONS_FLAG); //PERMISSIONS_FLAG 避免在onActivityResult方法里错乱 } @Override public void cancel() {} }); } mPopUpWindowPermission.show(mHintContent); } //进行回调跳转 public void startResult(Intent intent, int requestCode, CallbackResult callback) { mCallbackMap.put(requestCode,callback); startActivityForResult(intent,requestCode); } /** * * @param permissions 权限 * @param requestCode 请求码 * @param content 提示用户文字 * @param callback 回调 */ public void requestPermissions(String[] permissions, int requestCode,String content, CallbackPermissi callback) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if(null == permissions || permissions.length <= 0 || null == getContext()){ return; } //保存对应的请求码和回调对象 mCallbackPermissionsMap.put(requestCode,callback); mHintContent = content; //窗口提示语 //当前两个变量是用来处理用户跳转到系统授权页面操作后,返回回时,可能并没有授权,需要二次判断权限 mCurrentCode = requestCode; mCurrentPermissions = permissions; //权限都满足的情况下直接回调成功 if(Utils.isPermission(getContext(),permissions)){ //操作完成就移除任务 CallbackPermissi callbacks = mCallbackPermissionsMap.remove(requestCode); if(null != callbacks){ callbacks.onPermissionSucceed(requestCode); } }else{ //不满足情况下 直接申请权限 requestPermissions(permissions,requestCode); } }else{ //低于6.0直接回调成功 callback.onPermissionSucceed(requestCode); } } }
提供两个接口,一个是权限回调,一个是数据回调
public interface CallbackPermissi { void onPermissionSucceed(int requestCode); void onPermissionFailed(int requestCode); }public interface CallbackResult { public void onActivityResult(int requestCode, int resultCode, Intent data); }
提供用户是否授权的窗口public class PopUpWindowPermission implements View.OnClickListener { private PopupWindow mPopupWindow; private OnClick mOnClick; private FragmentActivity mActivity; private TextView mContentTv; public PopUpWindowPermission(FragmentActivity activity, OnClick click){ mOnClick = click; mActivity = activity; initView(activity); } private void initView(FragmentActivity activity) { View inflate = LayoutInflater.from(activity).inflate(R.layout.pop_permission, null); inflate.findViewById(R.id.config_btn).setOnClickListener(this); inflate.findViewById(R.id.cancel_btn).setOnClickListener(this); mContentTv = (TextView) inflate.findViewById(R.id.msg_tv); mPopupWindow = new PopupWindow(inflate, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); mPopupWindow.setBackgroundDrawable(new BitmapDrawable()); mPopupWindow.setOutsideTouchable(true); mPopupWindow.setFocusable(true); } public void show(String content){ mContentTv.setText(content); mPopupWindow.showAtLocation(mActivity.getWindow().getDecorView(), Gravity.CENTER, 0, 0); } public void dismiss(){ mPopupWindow.dismiss(); } @Override public void onClick(View view) { if(view.getId() == R.id.config_btn){ mOnClick.config(); }else{ mOnClick.cancel(); } dismiss(); } public interface OnClick{ void config(); void cancel(); } }