目錄html
Loonandroid是一個註解框架,不涉及任何UI效果,目的是一個功能一個方法,以方法爲最小顆粒度對功能進行拆解。把功能傻瓜化,簡單化,去掉重複性的代碼,隱藏複雜的實現。以便團隊合做或者後期修改變得簡單。說框架是誇大了,主要是由於我比較喜歡偷懶,對於一個碼農來講,可以偷懶,而且在不影響項目質量的狀況下,是不容易的。android
不少朋友看到註解就就要吐槽,會影響性能什麼的。註解,確實會影響性能。經過註解自動注入,反射會讓程序變慢50~100毫秒左右,從體驗感基本感受不出來.硬件性能好的手機能夠忽略,通過測試無需太大的擔憂。我是作外包的,初衷是在不影響項目質量的前提下減小個人工做量,並且BUG其餘人改起來相對比較容易,本工具專屬外包碼農,若是你想作精細,很在乎性能數據,請看看就好。
- - -
LoonAndroid 3
是LoonAndroid改良版,以前的版本存在內存沒法釋放的問題。增長了一些新的功能,讓開發變得非主流。git
特別聲明:
版本3x框架還未在實際生產中驗證,目前只擁有demo和我改造的一個項目,請當心謹慎,若有使用,請告知我,我會跟蹤相應BUG以及性能,以作到及時修復。
o2oDemo這個是我根據別人項目改寫的,沒改寫完,沒改動界面,沒有改動工具類,只改動了activity和adapter以及網絡請求程序員
一、基本功能github
二、適配器功能web
三、綜合功能集合面試
四、傻瓜式下拉刷新ajax
五、自定義模塊類緩存
六、傻瓜式組件類微信
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<String, Object> 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<String, String> params = new HashMap<String, String>(); 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<String, Object> 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 網絡請求能夠切換網絡核心,框架只負責分發,力求傻瓜化,來適應外包敏捷開發
等等
LoonAndroid 1X 已經上線並告訴個人項目
面吧:一個朋友開發的軟件,轉爲程序員面試使用的神器
酷魚: 新財富集團的APP 資本人的社交圈
寶貝計劃:「寶貝計劃」是大連地區專一於兒童教育領域的APP。
泵閥通:是由明做網絡在移動互聯網領域針對泵閥產業推出的跨時代新媒體
大歌星:娛樂K歌應用,把手機成爲錄間棚,原版伴奏供你選擇。
古道網:是一款記錄、分享古代道路的手機應用
拍手吧:高品質音樂,獨特的遊戲,海量電子書,超好玩的應用軟件以及社交體驗
在使用中有任何問題,歡迎反饋給我,能夠用如下聯繫方式跟我交流
有意也好,無心也罷,至少寫了一個東西,有欣喜,也還有汗水,有謾罵,有沮喪,但願你喜歡個人做品,同時也能支持一下。