官方项目地址:github AA
简介
在浏览项目的首页之后,通过对比可以清楚的看到,相比android原生的开发方式,AA能够使我们的代码精简不少。省去了繁琐的控件查找、事件绑定,让我们专注业务处理。这仅仅只是它强大功能的一角。
AA的特性
- 依赖注入(DI),可以注入view,extra,资源,服务。方便我们编程,变相的减少了代码错误的可能性。
- 简化的线程模型。UI线程,background后台操作耗时联网请求。
- 事件绑定 非常方便的事件绑定机制,不再需要丑陋的匿名内部 listener类了。
- REST Client 依赖于spring rest,要求后端服务的接口是restful风格的。
- No Magic 不知道表达的是什么意思。AA的机制是使用的注解是编译注解,就是在程序编译的时候才编译解释,生成一个同当前类名带下划线的类,如MainActivity_ ,而不是使用反射,所以效率同原生开发方式。
Android studio中配置
需要在项目的build.gradle中进行加入一些配置(带注释的部分)
` buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4+'
` }
}
allprojects { //所有项目依赖的仓库地址,也可以配置maven,
//但是jcenter是专门为android定制提供的,比maven好,忘记在哪里看
//到的这句话了,自己的项目中配置了这个allprojects才会自动下载AA的依赖
repositories {
jcenter()
}
}`
同时,模块下的buil.gradle文件也需要配置:
`apply plugin: 'com.android.application'
apply plugin: 'android-apt'
def AAVersion = '3.2+'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.sondon.mayi.hii"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
`
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
apt "org.androidannotations:androidannotations:$AAVersion"
compile "org.androidannotations:androidannotations-api:$AAVersion"
compile 'com.android.support:appcompat-v7:22.1.1'
compile 'com.android.support:support-v4:22.1.1'
}
`
apt {
arguments {
androidManifestFile variant.outputs[0].processResources.manifestFile
// if you have multiple outputs (when using splits), you may want to have other index than 0
`
` // You can set optional annotation processing options here, like these commented options:`
` // logLevel `'INFO'
`// logFile ` ' /var/log/aa.log '
`
}
}`
`
排版有点丑,第一次使用markdown,还在摸索中。
例子
对于使用,一定要在清单文件中使用带下划线的类。如,MainActivity_
请注意看代码中的onPreExcute,doInback(),onPostExcute()三个,方法,提供了很好的UI,后台操作模型。
直接上例子吧。一下的代码,都是在同一个类中。
这里写代码片` @EActivity(R.layout.activity_login)`
`public class LoginActivity extends Activity implements `RestErrorHandler {`
`private static final String TAG = LoginActivity.class.getSimpleName();`
//可以这样使用,是因为id和变量名一样,不一样的话,需要自己绑定
@ViewById
EditText etUserName;
@ViewById
EditText etPassword;
@ViewById
CheckBox cbRememberPassword;
@ViewById
CheckBox cbAutoLogin;
@ViewById
Button btnLogin;
//注入rest client
@RestService
MyRestClient mRestClient;
//sharedpreferens的使用
@Pref
LoginPrefs_ mPrefs;
private Dialog mloadingDialog;
/**
* 可以在这里 初始化 http
*/
@AfterInject
void afterInject() {
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setConnectTimeout(2*1000);
mRestClient.getRestTemplate().setRequestFactory(requestFactory);
mRestClient.setRestErrorHandler(this);
}
/**
* 执行完控件绑定之后执行
*/
@AfterViews
void afterViews() {
String username = mPrefs.username().get();
String password = mPrefs.password().get();
boolean isRmemberpassWord = mPrefs.isRmemberpassWord().get();
boolean isAutoLogin = mPrefs.isAutoLogin().get();
etUserName.setText(username);
etPassword.setText(password);
cbRememberPassword.setChecked(isRmemberpassWord);
cbAutoLogin.setChecked(isAutoLogin);
if (isAutoLogin) {
doInBackground(username, password);
}
// TODO 为了方便测试
`// btnLogin.setEnabled(true);
}
@Click(R.id.btnLogin)
public void btnLogin(View v) {
Log.d(TAG, "btnLogin()");
if(!APKUtils.isNetWorkAvailable(getApplicationContext())){
Toast.makeText(getApplicationContext(), "网络不可用", 1).show();
}
String username = etUserName.getText().toString().trim();
String password = etPassword.getText().toString().trim();
if (TextUtils.isEmpty(username)) {
Toast.makeText(getApplicationContext(), "请输入用户名!", Toast.LENGTH_LONG).show();
return;
}
if (TextUtils.isEmpty(password)) {
Toast.makeText(getApplicationContext(),"请输入密码!", Toast.LENGTH_LONG).show();
return;
}
doInBackground(username, password);
}
//后台执行耗时操作,不能在这里更新UI
@Background
public void doInBackground(String username, String password) {
Log.d(TAG, "doInBackground()");
Log.d(TAG, "doInBackground() username :"+username);
Log.d(TAG, "doInBackground() password:"+password);
onPreExecute();
// TODO 测试 rest api
// String result = mRestClient.getInfo();
BaseRequest br = CacheUtils.getBaseRequest(this);
LoginRequest request = new LoginRequest();
request.baseRequest = br;
request.userName = username;
request.password = password;
Log.d(TAG, "doInBackground() request:" + request);
String result ="";
// result = mRestClient.login(request);
Log.d(TAG, "doInBackground() request DeviceType:" + br.deviceType);
Log.d(TAG, "doInBackground() request CustomerId:" + br.customer_id);
Log.d(TAG, "doInBackground() request DeviceID:" + br.deviceID);
Log.d(TAG, "doInBackground() request rootUrl:" + mRestClient.getRootUrl());
onPostExecute(result);
}
//UI 线程,可以在这里操作UI
@UiThread
public void onPreExecute() {
Log.d(TAG, "onPreExecute()");
mloadingDialog = CustomerProgressDialog.createLoadingDialog(
LoginActivity.this, "正在登陆...");
mloadingDialog.show();
}
@UiThread
public void onPostExecute(String result) {
Log.d(TAG, "onPostExecute() result :"+result);
mloadingDialog.dismiss();
// if(result==null)
// return;
// 获取登陆结果,跳转到mainactivity
MainActivity_.intent(LoginActivity.this).localUser(etUserName.getText().toString()).start();
/* Intent intent =new Intent(LoginActivity.this ,MainActivity.class);
startActivity(intent);*/
//存储用户名
mPrefs.username().put(etUserName.getText().toString().trim());
boolean isRemenberPwd = cbRememberPassword.isChecked();
boolean isAutoLogin = cbAutoLogin.isChecked();
if(isRemenberPwd || isAutoLogin){
mPrefs.password().put(etPassword.getText().toString().trim());
}else{
mPrefs.password().put(null);
}
mPrefs.isAutoLogin().put(isAutoLogin);
mPrefs.isRmemberpassWord().put(isRemenberPwd);
finish();
}
//TextView中的文字更改执行
@TextChange({ R.id.etUserName, R.id.etPassword })
public void textChanged() {
if (TextUtils.isEmpty(etUserName.getText().toString())
|| TextUtils.isEmpty(etPassword.getText().toString())) {
btnLogin.setEnabled(false);
} else {
btnLogin.setEnabled(true);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if(mloadingDialog!=null){
mloadingDialog.dismiss();
}
}
return false;
}
@UiThread
@Override
public void onRestClientExceptionThrown(RestClientException e) {
// TODO Auto-generated method stub
mloadingDialog.dismiss();
e.printStackTrace();
Toast.makeText(this, "访问失败 " , Toast.LENGTH_SHORT).show();
}
}`