Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android快速開發框架LoonAndroid3

Android快速開發框架LoonAndroid3

編輯:關於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、傻瓜式組件類

  • 獲取圖片組件
  • 登錄組件

使用

  1. 在項目的Application中進行初始化
  2. 在assets目錄下面mvc.properties的配置設置如下
  3. 引入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 網絡請求可以切換網絡核心,框架只負責分發,力求傻瓜化,來適應外包敏捷開發 等等


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved