OOP与AOP的关系
AOP(面向切面)是OOP(面向对象)的补充
OOP思想
OOP是将通用的逻辑封装成对象的方法,然后代码块中调用该方法。
AOP思想
AOP是将通用逻辑分离出来,等到代码块被调用时再把通用逻辑切入代码块。
Android上的AOP三剑客
Android上的AOP三剑客:APT、AspectJ、Javassist。其中Javassist是操作字节码,学习成本大。接下来重点介绍APT和AspectJ。
APT和AspectJ都利用到了注解,需要编写注解解析器。它们的区别如下:
APT的注解解析器会根据注解自动生成一个工具类,该工具类封装了通用逻辑。程序员需要手动调用工具类的方法来切入通用逻辑。
AspectJ的注解解析器是在编译时扫描文件,然后根据注解自动将通用逻辑切入代码中。
举个例子
下面分别演示了三种“请求运行时权限”的方法:常规方法、PermissionsDispatcher(APT)Aopermission(AspectJ)。
常规方法
//请求权限
ActivityCompat.requestPermissions(mActivity, permissions, permissionRequestCode);
//接收权限的请求结果
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
}
PermissionsDispatcher(APT)
首先写注解。
@RuntimePermissions
public class MainActivity extends AppCompatActivity {
// 单个权限
// @NeedsPermission(Manifest.permission.CAMERA)
// 多个权限
@NeedsPermission({ Manifest.permission.CAMERA })
void showCamera() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.sample_content_fragment, CameraPreviewFragment.newInstance())
.addToBackStack("camera")
.commitAllowingStateLoss();
}
// 用户拒绝授权回调(可选)
@OnPermissionDenied(Manifest.permission.CAMERA)
void showDeniedForCamera() {
Toast.makeText(this, R.string.permission_camera_denied, Toast.LENGTH_SHORT).show();
}
// 用户勾选了“不再提醒”时调用(可选)
@OnNeverAskAgain(Manifest.permission.CAMERA)
void showNeverAskForCamera() {
Toast.makeText(this, R.string.permission_camera_neverask, Toast.LENGTH_SHORT).show();
}
}
注解写好后,Build ——> Make Module ***,PermissionsDispatcher 会生成一个 MainActivityPermissionsDispatcher(Activity Name + PermissionsDispatcher),你可以使用它来安全地访问这些受权限保护的方法。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button_camera).setOnClickListener(v -> {
// 调用带权限检查的 showCamera 方法
MainActivityPermissionsDispatcher.showCameraWithCheck(this);
});
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// 代理权限处理到自动生成的方法
MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}
Aopermission(AspectJ)
btn_click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callMap();
}
});
/**
* 申请权限
*/
@NeedPermission(value = {Manifest.permission.ACCESS_FINE_LOCATION}, requestCode = 0)
private void callMap() {
Toast.makeText(this, "定位权限申请通过", Toast.LENGTH_SHORT).show();
}
/**
* 权限被取消
*
* @param bean CancelBean
*/
@PermissionCanceled
public void dealCancelPermission(CancelBean bean) {
Toast.makeText(this, "requestCode:" + bean.getRequestCode(), Toast.LENGTH_SHORT).show();
}
/**
* 权限被拒绝
*
* @param bean DenyBean
*/
@PermissionDenied
public void dealPermission(DenyBean bean) {
Toast.makeText(this,
"requestCode:" + bean.getRequestCode()+ ",Permissions: " + Arrays.toString(bean.getDenyList().toArray()), Toast.LENGTH_SHORT).show();
}
声明一个public方法接收权限被取消的回调,方法必须有一个CancelBean类型的参数。
声明一个public方法接收权限被拒绝的回调,方法必须有一个DenyBean类型的参数。
有关PermissionsDispatcher和Aopermission可以查看下面的2篇文章:
PermissionsDispatcher,Android 6.0 运行时权限
Android 采用AOP方式封装6.0权限管理