前言
AndroidAnnotations 虽然使用注解,但基本性能不受影响, 原理是因为 因为这个注入框架在编译时候,会生成一个子类, 比如说MainActivity对映会生成个子类为MainActivity_
一.AS中的配置
1.在全局的build.gradle中添加这行代码
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
2.moodule内部的build.gradle 4.0.0是AndroidAnnotations的发布版本已经到了4.0.0,这里的版本号可以替换成当前最新的版本号
apply plugin: 'com.android.application'
apply plugin: 'android-apt'
def AAVersion = '4.0.0'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
apt "org.androidannotations:androidannotations:$AAVersion"
compile "org.androidannotations:androidannotations-api:$AAVersion"
}
apt {
arguments {
androidMainfestFile variant.outputs[0].processResources.manifestFile
}
}
二.AA框架注入组件(Components)方法学习
1.EActivity
需要在 AndroidManifest里面修改,添加一个下划线, 这是AA注解使用时候编译生成的子类在使用注解后,并不能找到下划线的类,必须点击这里编译一下
@EActivity(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {
}
<activity android:name=".MainActivity_">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>不仅要
需要注意的是,假如这里有个点击事件,跳转到了第二个页面,这里的TwoActivity在这里如果使用了注解@EActivity注解,不仅要在AndroidManifest修改,也要把Intent中的值修改一下
Intent intent1=new Intent(this,TwoActivity_.class);
startActivity(intent1);
2.EApplication / App
@EApplication
public class MyApp extends Application {
private Map<String,Object> mMap=new HashMap<>();
@Override
public void onCreate() {
super.onCreate();
mMap.put("key","我要成为大牛");
}
public Map<String,Object> getMap(){
return mMap;
}
}
同样 在AndroidManifest中也要修改
<application
android:name=".MyApp_"
在代码中取出Map集合
@App
MyApp mApp;
Map<String, Object> map = mApp.getMap();
Toast.makeText(MainActivity.this, map.get("key").toString(), Toast.LENGTH_SHORT).show();
3.EBean /Bean
使用@EBean 注解
@EBean
public class PersonBean {
private String userName;
private String password;
public PersonBean() {
}
......
代码的使用 通过@Bean 来对当前的实体Bean进行注解(必须有无参构造函数), 然后可以直接使用
@Bean
PersonBean mPersonBean;
mPersonBean.setUserName("大牛");
mPersonBean.setPassword("123455");
Toast.makeText(MainActivity.this, "帐号信息为: "+mPersonBean.toString(), Toast.LENGTH_SHORT).show();
@Bean(ImMemoryUserFinder.class)
UserFinder mUserFinder; //这里的UserFinder 是个接口, ImMemoryUserFinder是个接口的实现类
4.EViewGroup
@EViewGroup(R.layout.person_item)
public class UserItemView extends LinearLayout {
.......
UserItemView userItemView= UserItemView_.build(mContext);//系统提供了一个方法来new
5.EFragment
@EFragment 进行注解之后, 也会生成一个同名的下划线子类
@EFragment(R.layout.fragment_my)
public class MyFragment extends Fragment {
public MyFragment() {
}
}
@EActivity
public class FragActivity extends FragmentActivity { //清单文件需要改一下
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
}
}
xml文件的代码,注意这里也需要改一下
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.FragActivity">
<fragment
android:id="@+id/fragment"
android:name="aa.app.fragment.MyFragment_"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
6.EService
@EService
public class MyService extends Service{
@Override
public void onCreate() {
super.onCreate();
}
.......
同时,在AndroidManifest也需要修改一下,原理和@EActivity一样
<service android:name=".service.MyService_
然后在代码中启动服务,有两种启动方式,一种是Intent 还有一种是AA框架提供的方法,如下:
MyService_.intent(this).start();
7.EView 是对自定义View 的注解
@EView
public class MyButton extends Button {
public MyButton(Context context) {
在布局文件中也要修改成带下划线的
<aa.app.view.MyButton_
android:id="@+id/bt_View"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
三.AA框架 Injection标签使用介绍
1.Bean
一般从一个Activity跳转到另一个Activity中可以使用
@Extra("key")//如果这里不写key值,默认的key值为变量名
String message;
Intent intent=InjectionActivity_.intent(this).message("你好呀").get();
intent.setClass(this,ExtraActivity_.class);
this.startActivity(intent);
然后在EtraActivity
@EActivity(R.layout.activity_extra)
public class ExtraActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
// Intent intent1 = ExtraActivity_.intent(this).get();
Bundle bundle = intent.getExtras();
if (bundle!=null){
Toast.makeText(ExtraActivity.this, "extra 的数据为"+bundle.getString("key"), Toast.LENGTH_SHORT).show();
}
}
}
3.AfterExtras
对附加变量使用的一个操作,注入的方法, 会在@Extra 执行
4.AfterInject
也是关于生命周期的方法 ,比如说在使用@Bean注解之后的一个方法,可以在这里对其中进行初始化操作之类的
@AfterInject
public void showAfterInjectThing(){
Toast.makeText(MainActivity.this, "我已经被注入了....", Toast.LENGTH_SHORT).show();
}
5.ViewById
注意一点 在xml里面声明的id 和 在代码中声明的变量名 必须一致
6.AfterViews
当执行onCreate()方法的时候,@ViewById 还没有注入进去,所以才AA框架才提供了@AfterViews
@ViewById
TextView tv_afterViews;
@AfterViews
public void initViews(){
tv_afterViews.setText("View被注入后的操作");
}
7.RootContext
通常在一般的类中使用,获取到上下文的引用,(本人测试,在Activity中使用会报错)
@RootContext
Context mContext;
8.SystemService
例如:
@SystemService
ConnectivityManager mConnectivityManager; //这样就已经获取了系统的服务了
.....
//未使用之前的写法: ConnectivityManager mConnectivityManager= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
//获取NetWorkInfo对象
NetworkInfo[] allNetworkInfo = mConnectivityManager.getAllNetworkInfo();
if(allNetworkInfo!=null && allNetworkInfo.length>0){
for (int i = 0; i <allNetworkInfo.length; i++) {
if(allNetworkInfo[i].getState()==NetworkInfo.State.CONNECTED){
Toast.makeText(InjectionActivity.this, "当前有网络....", Toast.LENGTH_SHORT).show();
}
}
}
四.AA框架 事件绑定(Event Binding)使用
1.TextChange
2.AfterTextChange
3.BeforeTextChange
对比两种写法
setContentView(R.layout.activity_event_binding) //如果两种写法写在同一个类中,这里需要写这个,不然et_change会报空指针
EditText et_change= (EditText) findViewById(R.id.et_change);
et_change.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
使用AA框架后的写法
@ViewById
EditText et_AAchange;</span>
......
@BeforeTextChange</span>(R.id.et_AAchange)
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@TextChange(R.id.et_AAchange)
public void onTextChanged(CharSequence s, int start, int before, int count) { }
@AfterTextChange(R.id.et_AAchange)
public void afterTextChanged(Editable s) { }
4.FoucsChange
主要用于控件有没有获取到焦点
@FocusChange(R.id.et_AAchange)
public void focusChange(View view,boolean hasFocus){ //第一个参数是当前哪个焦点发生了变化
Log.i("tag","当前交点发生变化,状态为 : "+hasFocus);
}
5.CheckedChange
通常情况下用于RadioGroup RadioButton 中使用
@CheckedChange({R.id.rb1,R.id.rb2})
public void radioChecked(CompoundButton view, boolean isChecked){ //选中时候返回的状态为true
if(view.getId()==R.id.rb1){
Log.i("tag","第一个rb的选中状态为 : "+isChecked );
}else{
Log.i("tag","第二个rb的选中状态为 : "+isChecked );
}
}
6.Touch
@Touch(R.id.bt_Touch)
public void touchButton(View view){
Log.i("tag","啊!我又被摸了....");
7.Click
@Click({R.id.bt_enter,R.id.bt_App,R.id.bt_Bean,R.id.bt_Frag,R.id.bt_Service,R.id.bt_View,R.id.bt_Injection,R.id.bt_EventBinding})
public void onclick(View view){
switch (view.getId()){
case R.id.bt_enter:
Intent intent1=new Intent(this,TwoActivity_.class);
startActivity(intent1);
break;
case R.id.bt_App:
Map<String, Object> map = mApp.getMap();
Toast.makeText(MainActivity.this, map.get("key").toString(), Toast.LENGTH_SHORT).show();
break;
case R.id.bt_Bean
:
...
8.LongClick
@LongClick(R.id.btn_longClick)
public void longClickButton(View view){ //多个button可以测试哪个被长点击了<pre name="code" class="html"> Toast.makeText(MainActivity.this, "当前Button被长点击了", Toast.LENGTH_SHORT).show();
}
9.ItemClick
ListView 和GridView
@ItemClick(R.id.listView)
public void showItemClick(int str){ //这里的参数可以为String 或者View
Log.i("tag","被点击的位置为: "+str);
}
五.AA框架 线程处理 Threading
(方法最好是public 一定不能为private)
1.Background(共享线程池,并行) BackgroundExecutor.cancelAll("id") (id,serial,delay)
@Background
public void newWork() {
try {
URL url=new URL("http://www.baidu.com");
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5000);
if(conn.getResponseCode()==200){
InputStream is = conn.getInputStream();
byte[] buf=new byte[1024];
....
@Background(id="test01") //可以根据id值 取消任务
public void newWork() {
try {
URL url=new URL("http://www.baidu.com");
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5000);
if(conn.getResponseCode()==200){
InputStream is = conn.getInputStream();
byte[] buf=new byte[1024];
....
@Background(serial="test") //默认共享线程池是并行运行 现在是串行运行
@
@Background(delay=2000) //方法执行的时候,会延迟2000毫秒
还提供了一个取消线程任务的方法
BackgroundExecutor.cancelAll(id,boolean); //第一个是id,是否打断当前任务 true是
2.UiThread子线程中的代码不能操作ui 可以抽取成方法,然后方法用UIThread注入,确保能在主线程中操作
3.SupposeBackground 确保子线程运行注解的方法必须在子线程中运行
new Thread(new Runnable() {
@Override
public void run() {
setViews("子线程中要在主线程中操作数据");
}
}).start();
@SupposeBackground
public void supposeBackgroundNoUiThread(){
Log.i("tag","一定要在子线程中运行");
}
4.SupposeUiThread 确保主线程运行
注解的方法必须在主线程中运行
supposeUiThread();//必须在主线程调用
@SupposeUiThread
public void supposeUiThread(){
Log.i("tag","方法一定要在主线程中运行");
}