android注解框架实现,GitHub - huangyuanlove/AndroidAnnotation: Android注解框架,辅助快速开发...

编译时注解框架

新增AndroidStudio插件

change log

新增 广播接收器支持permission

新增 广播接收器支持flag

新增 广播接收器支持priority

优化PermissionUtil

引用

implementation 'com.huangyuanlove:view-inject-api:1.1.1'

implementation 'com.huangyuanlove:view-inject-annotation:1.1.0'

annotationProcessor 'com.huangyuanlove:view-inject-compile:1.1.0'

混淆

如果开启了混淆,则需要在混淆文件中配置

-keep public class com.huangyuanlove.view_inject_annotation.**

-keep public class com.huangyuanlove.view_inject_api.**

-keep public class com.huangyuanlove.view_inject_compiler.**

-keep public class **$$Router

-keep public class **$ViewInjector {

**[] $VALUES;

public *;

}

view-inject-annotation1.1.1 变更

权限相关优化

1.1.1之前的版本(不包含1.1.1)在使用PermissionUtil时,从流程上来讲还是挺繁琐的:

先调用PermissionUtil.hasSelfPermissions来检测是否有权限

然后调用PermissionUtil.shouldShowRequestPermissionRationale判断是否需要弹出权限说明窗

最后调用ActivityCompat.requestPermissions来请求权限

然后在重写Activity的onRequestPermissionsResult方法,在该方法中通过PermissionUtil.onRequestPermissionsResult(this,requestCode,permissions,grantResults,new PermissionUtil.RequestPermissionResult())判断用户对权限的响应

优化之后,我们只需要new Permissions(this).requestPermissions(int requestCode, PermissionFragment.OnPermissionResult onPermissionResult, String... permissions)这个方法就好了,代码如下:

PermissionFragment.OnPermissionResult onPermissionResult = new PermissionFragment.OnPermissionResult() {

@Override

public void onPermissionResult(int requestCode, ArrayList grantPermission, ArrayList shouldShowRationalePermission, ArrayList neverAskAgainPermission) {

Log.e("huangyuan","grantPermission:"+grantPermission);

Log.e("huangyuan","shouldShowRationalePermission:"+shouldShowRationalePermission);

Log.e("huangyuan","neverAskAgainPermission:"+neverAskAgainPermission);

}

};

new Permissions(this).requestPermissions(AUDIO_PERMISSION, onPermissionResult, Manifest.permission.RECORD_AUDIO);

实现PermissionFragment.OnPermissionResult接口

创建Permissions

调用Permissions的实例方法requestPermissions,第一个参数为int类型requestCode,第二个参数为步骤1中的实现类,后面的不定长参数是需要申请的权限

Q:为什么在Activity和Fragment中同时重写了onRequestPermissionsResult方法,在Fragment中收不到回调?

A:在Activity中使用ActivityCompat.requestPermissions来申请权限,在Fragmen中直接使用requestPermissions申请权限;如果Fragment和Activity同时重写了onRequestPermissionsResult方法,则需要在Activity重写的方法中调用super.onRequestPermissionsResult,这样Fragment中才会收到回调。至于为什么,RTFSC。

以下是1.1.0版本说明

@BindView

使用方法:

在application module中

@BindView(id = R.id.xxx)

protected Button buttonOne;

在 library module中

@BindView(idStr = "xxx")

protected Button buttonTwo;

需要注意的是:字段的访问修饰符权限必须大于 protected,在字段使用前调用(一般是在OnCreate、onCreateView)ViewInjector.bind(this);

Activity示例: TestViewInjectActivity.java

Fragment示例: TestViewInjectFragment.java

Adapter示例: ListViewAdapter

@ClickResponder

在application module中

@ClickResponder(id = {R.id.xxx,R.id.yyy})

public void onClickButtonOne(View v) {

Toast.makeText(TestViewInjectActivity.this, "test_view_inject_one", Toast.LENGTH_SHORT).show();

}

在 library module中

@ClickResponder(idStr = {"xxx","yyy"})

public void onClickButtonTwo(View v) {

Toast.makeText(TestViewInjectActivity.this, "test_view_inject_two", Toast.LENGTH_SHORT).show();

}

需要注意的是:方法的访问修饰符权限必须大于 protected,在方法使用前调用(一般是在OnCreate、onCreateView)ViewInjector.bind(this);

支持同一个方法绑定到多个view

@LongClickResponder

在 application module中

@LongClickResponder(idStr = {"test_view_inject_two"})

public void onLongClickButtonTwo(View v){

Toast.makeText(TestViewInjectActivity.this, "long click button two", Toast.LENGTH_SHORT).show();

}

在 library module 中

@LongClickResponder(id = R.id.test_long_click)

public void onLongClick(View v){

Toast.makeText(TestViewInjectActivity.this, "test_long_click", Toast.LENGTH_SHORT).show();

}

需要注意的是:方法的访问修饰符权限必须大于 protected,在方法使用前调用(一般是在OnCreate、onCreateView)ViewInjector.bind(this);

支持同一个方法绑定到多个view

@IntentValue

用来代替 getIntent().getXXX 或者Fragment中的getArguments().getXXX

使用方式:

@IntentValue(key = "String")

String value = "default"

@IntentValue(key = "parcelableObject",type = IntentValue.PARCELABLE_OBJECT)

ParcelableObject parcelableObject;

@IntentValue(key = "parcelableObjects" ,type = IntentValue.PARCELABLE_ARRAY_OBJECT)

ParcelableObject[] parcelableObjects;

@IntentValue(key = "parcelableObjectArrayList",type = IntentValue.PARCELABLE_ARRAYLIST_OBJECT)

ArrayList parcelableObjectArrayList;

@IntentValue(key = "serializableObject",type = IntentValue.SERIALIZABLE_OBJECT)

UnParcelableObject serializableObject;

注意:

如果传递的是Parcelable对象,type声明为IntentValue.PARCELABLE_OBJECT

如果传递的是Parcelable对象数组,type声明为IntentValue.PARCELABLE_ARRAY_OBJECT

如果传递的是Parcelable对象ArrayList,type声明为IntentValue.PARCELABLE_ARRAYLIST_OBJECT

如果传递的是序列化对象(实现了Serializable接口),type声明为IntentValue.SERIALIZABLE_OBJECT

在字段使用前(一般是在Activity的onCreate或者Fragment的onCreateView方法中)调用ViewInjector.parseBundle(this);

@UriValue

只支持如下几种类型,并且只能在Activity中使用

@UriValue(key = "name")

String name;

@UriValue(key = "id")

int id;

@UriValue(key = "double")

double aDouble;

@UriValue(key = "float")

float aFloat;

@UriValue(key = "long")

long aLong;

@UriValue(key = "boolean")

boolean aBoolean;

在字段使用前(一般是在Activity的onCreate方法中)调用ViewInjector.parseBundle(this);

@BroadcastResponder

广播分为本地广播和全局广播,注解接收广播接收器之后,需要自己去解注册

使用方式

public static final String NORMAL_LOCAL = "normal_local";

public static final String NORMAL_GLOBAL = "normal_global";

public static final String PERMISSION_GLOBAL = "permission_global";

public static final String BROADCAST_PERMISSION = "com.huangyuanlove.permission_broadcast";

//在 OnCreate 中注册广播接收器

HashMap> integerArrayListHashMap = ViewInjector.registerReceiver(this);

//使用注解定义接收广播的action 以及对应的回调方法

@BroadcastResponder(action = NORMAL_LOCAL)

void onReceiveNormalLocalBroadcast(Context context, Intent intent) {

showAction.setText("onReceiveNormalLocalBroadcast:"+intent.getAction());

}

@BroadcastResponder(action = NORMAL_GLOBAL,type = BroadcastResponder.GLOBAL_BROADCAST)

void onReceiveNormalGlobalBroadcast(Context context, Intent intent) {

showAction.setText("onReceiveNormalGlobalBroadcast:"+intent.getAction());

}

@BroadcastResponder(action = PERMISSION_GLOBAL,permission = BROADCAST_PERMISSION,type = BroadcastResponder.GLOBAL_BROADCAST)

void onReceivePermissionGlobalBroadcast(Context context, Intent intent) {

showAction.setText("onReceivePermissionGlobalBroadcast"+intent.getAction());

}

//在 onDestroy 中解注册

@Override

protected void onDestroy() {

super.onDestroy();

if(integerArrayListHashMap!=null){

ArrayList localReceiverList = integerArrayListHashMap.get(BroadcastResponder.LOCAL_BROADCAST);

if(localReceiverList!=null && localReceiverList.size()>0){

for(BroadcastReceiver receiver : localReceiverList){

LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);

}

}

ArrayList globalReceiverList = integerArrayListHashMap.get(BroadcastResponder.GLOBAL_BROADCAST);

if(globalReceiverList!=null && globalReceiverList.size()>0){

for(BroadcastReceiver receiver : globalReceiverList){

unregisterReceiver(receiver);

}

}

}

}

//发送广播

@ClickResponder(id= R.id.send_normal_local_broadcast)

public void sendNormalLocalBroadcast(View v){

Intent intent = new Intent();

intent.setAction(TestBroadcastActivity.NORMAL_LOCAL);

LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

}

@ClickResponder(id= R.id.send_normal_global_broadcast)

public void sendNormalGlobalBroadcast(View v){

Intent intent = new Intent();

intent.setAction(TestBroadcastActivity.NORMAL_GLOBAL);

sendBroadcast(intent);

}

@ClickResponder(id= R.id.send_permisson_global_broadcast)

public void sendPermissonGlobalBroadcast(View v){

Intent intent = new Intent();

intent.setAction(TestBroadcastActivity.PERMISSION_GLOBAL);

sendBroadcast(intent,TestBroadcastActivity.BROADCAST_PERMISSION);

}

以下是0.1.0版本的说明

//在 OnCreate 中注册广播接收器

HashMap broadcastReceiverHashMap = ViewInjector.registerReceiver(this);

//使用注解定义接收广播的action 以及对应的回调方法

@BroadcastResponder(action = {"com.huangyuanblog","com.huangyuanblog.www"})

public void onReceiveBroadcast(Context context, Intent intent){

Toast.makeText(context,intent.getAction(),Toast.LENGTH_SHORT).show();

}

//type默认本地广播,接收全局广播需要指定type = BroadcastResponder.GLOBAL_BROADCAST

@BroadcastResponder(action = {"com.huangyuanlove",Intent.ACTION_AIRPLANE_MODE_CHANGED},type = BroadcastResponder.GLOBAL_BROADCAST)

public void onReceiveBroadcastOther(Context context, Intent intent){

Toast.makeText(context,intent.getAction(),Toast.LENGTH_SHORT).show();

}

//在 onDestroy 中解注册

@Override

protected void onDestroy() {

super.onDestroy();

if(broadcastReceiverHashMap!=null){

if(broadcastReceiverHashMap.get(BroadcastResponder.GLOBAL_BROADCAST) !=null){

unregisterReceiver(broadcastReceiverHashMap.get(BroadcastResponder.GLOBAL_BROADCAST));

}

if(broadcastReceiverHashMap.get(BroadcastResponder.LOCAL_BROADCAST) !=null){

LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiverHashMap.get(BroadcastResponder.LOCAL_BROADCAST));

}

}

}

需要注意的是,默认的广播接收器是本地广播,如果需要接收全局广播,比如打开飞行模式等,需要指定type = BroadcastResponder.GLOBAL_BROADCAST

千万别忘记解注册

@RouterModule and @RouterPath

相同的 schema 和 host 中不要有相同的path及path对应的方法名

相同的 schema 和 host 中不要有相同的path及path对应的方法名

相同的 schema 和 host 中不要有相同的path及path对应的方法名

在不同的Provider中提供相同的schema和host会导致Router被覆盖,无法保证路由目标的正确性。

一般以App的名字做schema,模块(module)的名字做host,目标Activity的类名做方法名及path。

比如App的名字为jandan,模块(module)名为 account,目标Activity的类名为LoginActivity

则对应Provider推荐这样写

@RouterModule(schema = "Jandan",host = "account")

public class AccountModuleRouterProvider {

@RouterPath(value = "login")

public void toLoginActivity(Context context, String userName){

Intent intent = new Intent(context,LoginActivity.class);

intent.put("userName",userName);

context.startActivity(intent);

}

}

//在其他类中使用

Router.to("Jandan://account/login").addParam(this,"userName").done(new Router.InvokeResultListener() {

@Override

public void onError(Exception e) {

Toast.makeText(EXT_MainActivity.this,e.toString(),Toast.LENGTH_SHORT).show();

}

@Override

public void onSuccess(Object o) {

}

});

Router的本质上是进行的方法调用,可以反依赖调用。就像工程中的app模块依赖example_lib模块,我们仍然可以在example_lib调用app中的方法。

当然正向调用也是可以的。

具体示例可以看example_lib中的EXT_MainActivity类调用app中MainProvider类方法

PermissionUtil

将要进行的动作,需要某项危险权限时,我们需要先校验权限 PermissionUtil.hasSelfPermissions

如果有权限,则进行动作。

如果没有权限,校验是否需要提示 PermissionUtil.shouldShowRequestPermissionRationale;如果需要提示,则弹出提示框,用户点了允许之后再申请权限。如果不需要提示,则直接申请权限;

申请权限的结果有三种:

授权onGrant

禁止onDenied

禁止并不在提示 onNeverAskAgain

相关博客

TODO

@BindView 代替 findViewById

@ClickResponder 代替 setOnClickListener

@LongClickResponder 代替 setOnLongClickListener

@IntentValue 代替 getIntent().getXXX

@UriValue 代替 getQueryParameter

@BroadcastResponder 代替 registerReceiver

@RouterModule、@RouterPath 来进行反依赖传递调用

PermissionUtil 申请权限

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值