編輯:關於Android編程
Loonandroid是一個注解框架,不涉及任何UI效果,目的是一個功能一個方法,以方法為最小顆粒度對功能進行拆解。把功能傻瓜化,簡單化,去掉重復性的代碼,隱藏復雜的實現。以便團隊合作或者後期修改變得簡單。說框架是誇大了,主要是因為我比較喜歡偷懶,對於一個碼農來說,能夠偷懶,並且在不影響項目質量的情況下,是不容易的。
很多朋友看到注解就就要吐槽,會影響性能什麼的。注解,確實會影響性能。通過注解自動注入,反射會讓程序變慢50~100毫秒左右,從體驗感基本感覺不出來.硬件性能好的手機可以忽略,經過測試無需太大的擔心。我是做外包的,初衷是在不影響項目質量的前提下減少我的工作量,而且BUG其他人改起來相對比較容易,本工具專屬外包碼農,如果你想做精細,很在意性能數據,請看看就好。
LoonAndroid 3是LoonAndroid改良版,之前的版本存在內存無法釋放的問題。增加了一些新的功能,讓開發變得非主流。
特別聲明:如有BUG,請告知我,我會跟蹤相應BUG以及性能,以做到及時修復。
o2oDemo是我根據別人項目改寫的,沒改寫完,沒改動界面,沒有改動工具類,只改動了activity和adapter以及網絡請求
1、基本功能
InLayer注解
InPlayer 注解
Activity生命周期注解
InView注解
InSource注解
InAll注解
後台進程注解
方法點擊事件注解
基類注解
自動Fragment注解
手動Fragment注解
2、適配器功能
無適配器
無參baseAdapter
自定義一adapter
自定義二adapter
自動綁定一adapter
自動綁定二adapter
通用適配器
3、綜合功能集合
網絡請求模塊
輸入驗證
跨進程通訊
Json格式化類
倒計時類
4、傻瓜式下拉刷新
Listview
Grid
橫向Scrollview
縱向Scrollview
橫向ViewPage
縱向ViewPage
WebView
5、自定義模塊類
自定義模塊XML中使用
自定義模塊變量使用
6、傻瓜式組件類
獲取圖片組件
登錄組件
使用
在項目的Application中進行初始化
在assets目錄下面mvc.properties的配置設置如下
引入loonandroid最新版jar以及依賴包dex.jar
public class App extends Application {
@Override
public void onCreate() {
app = this;
Ioc.getIoc().init(this);
super.onCreate();
}
}
#---------------------------框架基礎配置-----------------------------
#配置當前屏幕基於哪個分辨率開發 框架裡面所有縮放比例全部來源於此 默認 480 800
standard_w=720
standard_h=1280
#-------------------------設置只允許加載到框架中的包名---------------
#如果不設置,那麼默認遍歷Manifest中的package,多個可以以逗號隔開
permit=com.android.demo,com.loonandroid.pc.plug
#--------------------------設置不允許解析的包名------------------
#如果不設置,那麼默認遍歷Manifest中的package,多個可以以逗號隔開
limit=com.example.loonandroid2.R
示例
1 為你去掉繁瑣的findViewById
平時我們這麼寫
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
findViewById();
}
void findViewById(){
.....
.....
.....
.....
};
}
現在我們這麼寫
@InLayer(R.layout.welcome)
public class WelcomeActivity extends Activity {
// ----------------------------------------------
// View
@InAll
Views v;
static class Views {
public ViewFlow flow;
public CircleFlowIndicator circle;
}
}
2 獲取照片
以前我們這麼寫
點擊事件
public void onClick(View v) {
switch (v.getId()) {
case R.id.camera:
Intent intentCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 下面這句指定調用相機拍照後的照片存儲的路徑
intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), Constant.save_user_photo)));
startActivityForResult(intentCamera, 2);
bottomPhotoDialog.dismiss();
break;
case R.id.photo:
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, 1);
bottomPhotoDialog.dismiss();
break;
case R.id.cancle:
bottomPhotoDialog.dismiss();
break;
}
}
裁剪參數
private void startPhoto(Uri url) {
Intent intent = new Intent();
intent.putExtra(Util.IMAGE_URI, url);
intent.putExtra(Util.CROP_IMAGE_WIDTH, 300);
intent.putExtra(Util.CROP_IMAGE_HEIGHT, 300);
intent.putExtra(Util.CIRCLE_CROP, false);
intent.setClass(this, CropActivity.class);
startActivityForResult(intent, 3);
}
activity回調
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
// 如果是直接從相冊獲取
case 1:
if (data == null) {
return;
}
Uri uri = data.getData();
if (uri != null) {
startPhoto(uri);
}
break;
// 如果是調用相機拍照時
case 2:
picture = new File(Environment.getExternalStorageDirectory() + "/" + Constant.save_user_photo);
if (!picture.exists()) {
return;
}
Uri uri2 = Uri.fromFile(picture);
if (uri2 != null) {
startPhoto(uri2);
}
break;
// 取得裁剪後的圖片
case 3:
if (data != null) {
bitmap = BitmapFactory.decodeFile(data.getStringExtra(Util.CROP_IMAGE_PATH));
user_photo.setImageBitmap(bitmap);
upload_head(data.getStringExtra(Util.CROP_IMAGE_PATH));
}
break;
default:
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
現在我們這麼寫
@InLayer(R.layout.activity_getphoto)
public abstract class GetPhotoActivity extends Activity implements PluginPhoto {
@InAll
Views test;
class Views {
ImageView iv_photo;
@InBinder(listener = OnClick.class, method = "click")
Button bt_photo, bt_camera;
}
private void click(View v) {
switch (v.getId()) {
case R.id.bt_photo:
//從相冊獲取圖片
PhotoConfig config = new PhotoConfig();
config.aspectX = 1;
config.aspectY = 2;
config.outputX = 200;
config.outputY = 400;
photo(config);
break;
case R.id.bt_camera:
//從相機獲取圖片
camera();
break;
}
}
@Override
public void callBack(Object... args) {
Toast.makeText(this, "圖片路徑:"+args[1], Toast.LENGTH_SHORT).show();
System.out.println("-----------------------------");
test.iv_photo.setImageBitmap((Bitmap)args[0]);
}
}
3 登錄
以前這麼寫
public class LoginActivity extends Acitivity {
TextView login_bt, register;
EditText user_name, user_password, user_code;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
login_bt = (TextView) findViewById(R.id.login_bt);
register = (TextView) findViewById(R.id.register);
user_name = (EditText) findViewById(R.id.user_name);
user_password = (EditText) findViewById(R.id.user_password);
user_code = (EditText) findViewById(R.id.user_code);
}
/**
* 網絡請求回調
*/
AjaxCallBack callBack = new AjaxCallBack() {
@Override
public void callBack(ResponseEntity status) {
progressDimss();
switch (status.getStatus()) {
case FastHttp.result_ok:
HashMap data = JsonUtil.initJson(status.getContentAsString());
if (data.get("status").toString().equals("0")) {
showToast(data.get("data").toString());
} else {
App.app.setData("user_id", data.get("data").toString());
startActivity(new Intent(LoginActivity.this, MainActivity.class));
overridePendingTransition(0, 0);
finish();
}
break;
default:
showToast("連接失敗,請檢查網絡後重試");
break;
}
}
@Override
public boolean stop() {
return false;
}
};
public void click(View v) {
switch (v.getId()) {
case R.id.login_bt:
hideSoft(user_name);
hideSoft(user_password);
String name = user_name.getText().toString().trim();
String password = user_password.getText().toString().trim();
String code = user_code.getText().toString().trim();
if (name.length() == 0) {
showToast("用戶名不能為空");
return;
}
if (password.length() == 0) {
showToast("密碼不能為空");
return;
}
HashMap params = new HashMap();
params.put("username", name);
params.put("password", password);
showProgress();
FastHttp.ajax(Constant.url_login, params, callBack);
break;
case R.id.register:
startActivity(new Intent(LoginActivity.this, RegisterActivity.class));
overridePendingTransition(0, 0);
break;
}
}
}
現在這麼寫
會自動填入之前的用戶名密碼 會自動驗證 只要調用save()即可存儲登錄框中信息
只需要調用AccountEntity datas = getSave();即可獲得所有存儲的賬號信息
@InLayer(R.layout.activity_login)
public abstract class LoginActivity extends Activity implements PluginLogin{
@Override
public void i(LoginConfig config) {
config.init(R.id.ed_number, R.id.ed_password, R.id.ed_submit, R.id.ed_remember);
}
/**
* 當點擊登陸按鈕,會自動獲取輸入框內的用戶名和密碼,對其進行驗證
*/
@Override
public void onValiResult(View view) {
if (view == null) {
//驗證通過
App.app.http.u(this).login("aaa", "bbb");
}else{
//驗證失敗給出提示語
Toast.makeText(this, "賬號密碼不能為空", Toast.LENGTH_SHORT).show();
}
}
@InHttp(HttpUrl.LOGIN_KEY)
public void result(ResponseEntity entity){
if (entity.getStatus() == FastHttp.result_net_err) {
Toast.makeText(this, "網絡請求失敗,請檢查網絡", Toast.LENGTH_SHORT).show();
return;
}
if (entity.getContentAsString()==null||entity.getContentAsString().length()==0) {
Toast.makeText(this, "網絡請求失敗,請檢查網絡", Toast.LENGTH_SHORT).show();
return;
}
//解析返回的數據
HashMap data = Handler_Json.JsonToCollection(entity.getContentAsString());
int status = Integer.valueOf(data.get("status").toString());
if (status == 0) {
Toast.makeText(this, data.get("data").toString(), Toast.LENGTH_SHORT).show();
return;
}
save();
//清除保存的數據
//clear("bbb");清除賬號bbb的緩存
//clear();清除所有緩存
}
}
4 自動驗證輸入框
平時我們這麼寫
String name = user_name.getText().toString().trim();
String email = user_email.getText().toString().trim();
String mobile = user_mobile.getText().toString().trim();
String password = user_password.getText().toString().trim();
if (name.length() == 0) {
showToast("用戶名不能為空");
return;
}
if (password.length() == 0) {
showToast("密碼不能為空");
return;
}
if (password.length() < 6) {
showToast("密碼長度必須大於6位");
return;
}
if (email.length() == 0) {
showToast("郵箱不能為空");
return;
}
if (mobile.length() == 0) {
showToast("手機號碼不能為空");
return;
}
if (!deal.isChecked()) {
showToast("請先同意用戶協議");
return;
}
現在我們這麼寫
static class Views {
@InVa(value=VaPassword.class,index=1)
EditText tv_password;
@InVa(value=VaPasswordConfirm.class,index=2)
EditText tv_passwordconfirm;
@InVa(value=VaEmail.class,index=3)
EditText tv_email;
@InVa(value=VaMobile.class,index=4)
EditText tv_mobile;
@InVa(value=VaDate.class,index=5)
EditText tv_data;
@InVa(value=VaWeb.class,index=6)
EditText tv_web;
@InVa(value=VaCard.class,index=7)
EditText tv_card;
@InVa(msg = "不能為空",empty=false,index=8)
EditText tv_notnull;
@InVa(reg=Regex.LET_NUM_UNLINE_REG,msg="請輸入字母數字或下劃線",empty=false,index=9)
EditText tv_number;
@InBinder(listener=OnClick.class,method="click")
Button bt_onclick;
}
public void click(View view) {
Validator.verify(this);
}
@InVaOK
private void onValidationSucceeded() {
Toast.makeText(this, "驗證成功", Toast.LENGTH_SHORT).show();
}
@InVaER
public void onValidationFailed(ValidatorCore core) {
if(TextView.class.isAssignableFrom(core.getView().getClass())){
EditText editText = core.getView();
editText.requestFocus();
editText.setFocusable(true);
editText.setError(core.getMsg());
}
}
5 後台進程
啟動以前我們這麼寫
public class LanunchActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
startActivity(new Intent(WelecomeActivity.this, MenuActivity.class));
finish();
}
}).start();
}
}
啟動頁現在我們這麼寫
@InLayer(R.layout.activity_first)
public class WelecomeActivity extends Activity {
@Init@InBack
protected void init() throws InterruptedException {
Thread.sleep(3000);
startActivity(new Intent(WelecomeActivity.this, MenuActivity.class));
finish();
}
}
6 Fragment優化
現在我們這麼寫
@InLayer(value = R.layout.activity_fragment)
public class AutoFragmentActivity extends FragmentActivity {
/**
* {@link InBean}創建了一個Fragment 無需方法onCreateView
*/
@InBean
private AutoFragment fragment;
@Init
void init() {
System.out.println(fragment);
startFragmentAdd(fragment);
}
public void startFragmentAdd(Fragment fragment) {
FragmentManager fragmentManager = this.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fl_test, fragment);
fragmentTransaction.commit();
}
}
@InLayer(R.layout.activity_com)
public class AutoFragment extends Fragment {
@InView(binder = @InBinder(listener = OnClick.class, method = "click"))
Button top;
@Init
void init() {
System.out.println("fragment 初始化完畢");
}
@InBack
private void click(View view) {
System.out.println("這裡點擊以後進入後台進程");
}
@InListener(ids={R.id.top,R.id.bottom},listeners={OnClick.class})
private void l(View view){
Toast.makeText(view.getContext(), "父類中點擊了", Toast.LENGTH_SHORT).show();
}
}
還有很多比較有意思的功能 1 跨進程通訊 集成了tinybus 無需在activity和fragment中注冊即可食用 2 adapter去掉了很多不需要的代碼 3 網絡請求可以切換網絡核心,框架只負責分發,力求傻瓜化,來適應外包敏捷開發 等等
提起BroadcastReceiver大家都很熟悉,它和Activity,Service以及ContentProvider並稱為Android的四大組件(四大金剛),可見
一、廣播發送者&廣播接收者介紹1.廣播接收者廣播接收者簡單地說就是接收廣播意圖的Java類,此Java類繼承BroadcastReceiver類,重寫:public vo
簡介MPAndroidChart是PhilJay大神給Android開發者帶來的福利。MPAndroidChart是一個功能強大並且使用靈活的圖表開源庫,支持Androi
這篇接著上一篇2dcanvas硬件繪制,分析保存繪制結果的texture被合成到on screen framebuffer上的過程。 1.webkit為canvas元素對