zoukankan      html  css  js  c++  java
  • 学习进度条64

    使用方式

    1. 使用下面的一种方式去获取需要的权限

    PermissionGen.with(MainActivity.this)

        .addRequestCode(100)

        .permissions(

            Manifest.permission.READ_CONTACTS,

            Manifest.permission.RECEIVE_SMS,

            Manifest.permission.WRITE_CONTACTS)

        .request();

    or

    PermissionGen.needPermission(ContactFragment.this, 100, 

        new String[] {

            Manifest.permission.READ_CONTACTS, 

            Manifest.permission.RECEIVE_SMS,

            Manifest.permission.WRITE_CONTACTS

        }

    );

    2.重写 onRequestPermissionsResult 方法

    @Override public void onRequestPermissionsResult(int requestCode, String[] permissions,

          int[] grantResults) {

        PermissionGen.onRequestPermissionsResult(this, requestCode, permissions, grantResults);

    }

    3.回调

    正确:

    @PermissionSuccess(requestCode = 100)

    public void doSomething(){

        Toast.makeText(this, "Contact permission is granted", Toast.LENGTH_SHORT).show();

    }

    错误:

    @PermissionFail(requestCode = 100)

    public void doFailSomething(){

        Toast.makeText(this, "Contact permission is not granted", t.LENGTH_SHORT).show();

    }

    往往一个框架,简单的使用方式,背后大多数是非常复杂的架构或者设计模式,这个架构的代码量以及难度不是非常大,配合源码食用更佳。

    基本分析

    成员变量

    //保存需要的权限

    private String[] mPermissions;

    //请求码

    private int mRequestCode;

    //保存Activity or Fragment

    private Object object;

    构造方法

    //私有化了构造方法

    private PermissionGen(Object object) {

        this.object = object;

    }

    with方法

    很多开源库惯用的手法,既传入Activity or Fragment的方法,并且调用构造方法,我想这个大家应该不能理解。

    public static PermissionGen with(Activity activity){

        return new PermissionGen(activity);

    }

    public static PermissionGen with(Fragment fragment){

        return new PermissionGen(fragment);

    }

    赋值

    既然有了对象,接下来就是对对象的成员变量进行赋值了。

    //当然还有另外一种方式去添加 permissions 就是 needPermission 留个大家自己去思考咯

    public PermissionGen permissions(String... permissions){

        this.mPermissions = permissions;

        return this;

    }

    public PermissionGen addRequestCode(int requestCode){

        this.mRequestCode = requestCode;

        return this;

    }

    上述几个流程是非常简单的,如果你经常拆轮子,对于这些手法已经见怪不怪了,接下来就说说他是如果通过注解反射来进行权限申请已经回调的吧。

    核心分析

    requestResult

    在使用方式的第二步调用了 PermissionGen.onRequestPermissionsResult(this, requestCode, permissions, grantResults); ,这是一个重载的方法,主要是第一个参数会不同,this可以是指向的对象可以是Fragment or Activity,但是最终都回调到一个方法。

    public static void onRequestPermissionsResult(Activity activity, int requestCode, String[] permissions,int[] grantResults) {

        requestResult(activity, requestCode, permissions, grantResults);

    }

    public static void onRequestPermissionsResult(Fragment fragment, int requestCode, String[] permissions,int[] grantResults) {

        requestResult(fragment, requestCode, permissions, grantResults);

    }

    最终都调用以下方法:

    private static void requestResult(Object obj, int requestCode, String[] permissions,int[] grantResults){

        List<String> deniedPermissions = new ArrayList<>();

        for(int i=0; i<grantResults.length; i++){

            //每一天通过的权限

            if(grantResults[i] != PackageManager.PERMISSION_GRANTED){

                deniedPermissions.add(permissions[i]);

            }

        }

        //如果有没通过的权限就失败

        if(deniedPermissions.size() > 0){

            doExecuteFail(obj, requestCode);

        } else {

            doExecuteSuccess(obj, requestCode);

        }

    }

    使用注解的方式回调

    正确时的回调的放阿飞

    private static void doExecuteFail(Object activity, int requestCode) {

        //方法一

        Method executeMethod = Utils.findMethodWithRequestCode(activity.getClass(),PermissionFail.class, requestCode);

        //方法二

        executeMethod(activity, executeMethod);

    }

    方法一:

    public static <A extends Annotation> Method findMethodWithRequestCode(Class clazz,Class<A> annotation, int requestCode) {

        //循环这个对象中的方法

        for(Method method : clazz.getDeclaredMethods()){

            //判断每个方法的注解是不是符合 annotation(PermissionSuccess or PermissionFail)

            if(method.isAnnotationPresent(annotation)){

                //最后调用了这个方法,就不copy了,非常简单,判断他的 requestCode 

                if(isEqualRequestCodeFromAnntation(method, annotation, requestCode)){

                    return method;

                }

            }

        }

    return null;

    }

    方法二:

    通过反射我们拿到了需要的方法,接下来就是运行这个方法了

    private static void executeMethod(Object activity, Method executeMethod) {

        if(executeMethod != null){

            try {

                if(!executeMethod.isAccessible()) executeMethod.setAccessible(true);

                //运行这个方法

                executeMethod.invoke(activity, null);

            } catch (IllegalAccessException e) {

                e.printStackTrace();

            } catch (InvocationTargetException e) {

                e.printStackTrace();

            }

        }

    }

    是不是非常简单,简单明了的几步流程,然后我们再睡觉描一眼 PermisstionSuccess 与 PermisstionFail 两个类

    @Target(ElementType.METHOD)

    @Retention(RetentionPolicy.RUNTIME)

    public @interface PermissionFail {

        int requestCode();

    }

    @Retention(RetentionPolicy.RUNTIME)

    @Target(ElementType.METHOD)

    public @interface PermissionSuccess {

        int requestCode();

    }

  • 相关阅读:
    shell进行mysql统计
    java I/O总结
    Hbase源码分析:Hbase UI中Requests Per Second的具体含义
    ASP.NET Session State Overview
    What is an ISAPI Extension?
    innerxml and outerxml
    postman
    FileZilla文件下载的目录
    how to use webpart container in kentico
    Consider using EXISTS instead of IN
  • 原文地址:https://www.cnblogs.com/hhw12345/p/14910557.html
Copyright © 2011-2022 走看看