標籤:android style blog http io ar color os 使用
常做開發,怎麼能不用架構。架構不僅可以加快我們開發人員的開發效率,還能提高程式的可維護性所以花點時間來學習幾個比較優秀的架構還是很有必要的,這樣可以省去很多我們去寫單調重複的代碼的時間,專註功能邏輯的實現,快准狠地開發出優秀的產品。
本人更多的時間是在進行安卓開發,這裡選取介紹的架構是andbase,優點這裡我就不一一介紹了,不好的話我也不會花時間寫部落格來介紹它,項目地址:https://github.com/zhaoqp2010/andbase,官方網站http://www.amsoft.cn/post-47.html,裡面有展示效果的圖片,文檔,還有一個apk,可以安到手機上看看效果是不是你想要的,
我覺得效果還是不錯,比較符合主流趨勢,在github上下載下來之後解壓會得到兩個項目,一個是源碼,一個是demo,其中demo項目要引用源碼項目,所以用的時候要將兩個一起匯入,demo項目會自動去找源碼項目這個依賴,找不到的話就會在項目上顯示紅叉,好,現在都準備好了,讓我們開始分析源碼吧------〉
AbActivity是整個架構activity的基類,官方是建議activity繼承這個類的,這樣可以使你的項目有統一的結構,一會我們分析源碼的時候我們就會發現,這個類為我們提供了很多常用的視圖,比如標題列titlebar,底部欄,一些進度條,toast,dialog,handler,總之可以讓我們省去很多麻煩,當然你可以根據自己的需要再去擴充這個基類,那麼作為重中之重,我們這次分析的就是AbActivity類,let‘s go!!!
這個類大約有900行代碼,一點點分析是不太現實的,我這裡只是撿重點痛點來發表一下我的看法,相信弄懂了這些,這個類對你來說就是小case了。
這個類為了相容較低的api,繼承的是FragmentActivity,所以我們以後用的時候自然也可以使用FragmentActivity的屬性和方法。
然後看屬性,就像我們前面說的,既然這個類為我們提供很多方便的視圖,那麼自然就得有屬性去支援它們,這些屬性主要有調試標籤TAG,日誌開關D,載入進度條 ProgressDialog mProgressDialog;,從底部,中部,上部彈出的Dialog和對應的內容View,應用程式物件abApplication,各種LayoutParams,然後就是介面的結構了,
首先是RelativeLayout ab_base充當總布局,AbTitleBar mAbTitleBar作標題列布局,AbBottomBar mAbBottomBar 做底部欄布局,RelativeLayout contentLayout做內容布局,
還有一個幀測試的AbMonitorView mAbMonitorView和mMonitorHandler,這兩個我們暫時先不說,留到後面再講,然後就是視窗管理對象WindowManager mWindowManager和它的Params:mMonitorParams,最後還有一個baseHandler,是用來處理髮過來的非同步訊息的
private Handler baseHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case AbConstant.SHOW_TOAST:showToast(msg.getData().getString("Msg"));break;case AbConstant.SHOW_PROGRESS:showProgressDialog(mProgressMessage);break;case AbConstant.REMOVE_PROGRESS:removeProgressDialog();break;case AbConstant.REMOVE_DIALOGBOTTOM:removeDialog(AbConstant.DIALOGBOTTOM);case AbConstant.REMOVE_DIALOGCENTER:removeDialog(AbConstant.DIALOGCENTER);case AbConstant.REMOVE_DIALOGTOP:removeDialog(AbConstant.DIALOGTOP);default:break;}}};
接著看onCreate函數,挑重要的說,
//主標題列mAbTitleBar = new AbTitleBar(this);//最外層布局ab_base = new RelativeLayout(this);ab_base.setBackgroundColor(Color.rgb(255, 255, 255));//內容布局contentLayout = new RelativeLayout(this);contentLayout.setPadding(0, 0, 0, 0);//副標題列mAbBottomBar = new AbBottomBar(this); //填入Viewab_base.addView(mAbTitleBar,layoutParamsFW);RelativeLayout.LayoutParams layoutParamsFW2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);layoutParamsFW2.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);ab_base.addView(mAbBottomBar, layoutParamsFW2);RelativeLayout.LayoutParams layoutParamsFW1 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);layoutParamsFW1.addRule(RelativeLayout.BELOW, mAbTitleBar.getId()); //跟我們在xml中設定android:layout_below="@id/..."一樣layoutParamsFW1.addRule(RelativeLayout.ABOVE, mAbBottomBar.getId());ab_base.addView(contentLayout, layoutParamsFW1);
這裡就是剛才說的在整個布局裡添加標題列,底部欄,和顯示的主要內容,因為用的相對布局,而且是在代碼中設定的,可能這裡看起來比較費勁,尤其是addRule方法,之前不知道,跳到源碼中看了看其實就是在LayoutParams中有一個整形數組,屬性作為int儲存,我們設定的是屬性對應的值,就是這個方法
public void addRule(int verb, int anchor) { mRules[verb] = anchor; }
然後再挑著往下看,我們平常要用的函數就在這裡,包括彈出Toast,設定內容介面,這個有好幾個重載的函數,咱們看一個就懂了
public void setAbContentView(View contentView) {contentLayout.removeAllViews(); //先將原先的內容清掉contentLayout.addView(contentView,layoutParamsFF);//再將新加的布局加到內容中去,//iocinitIocView();}
我們看到這裡調用了一個initIocView方法,那麼就讓我們深入進去,
private void initIocView(){Field[] fields = getClass().getDeclaredFields();if(fields!=null && fields.length>0){for(Field field : fields){try {field.setAccessible(true);if(field.get(this)!= null )continue;AbIocView viewInject = field.getAnnotation(AbIocView.class);if(viewInject!=null){int viewId = viewInject.id(); field.set(this,findViewById(viewId));setListener(field,viewInject.click(),Method.Click);setListener(field,viewInject.longClick(),Method.LongClick);setListener(field,viewInject.itemClick(),Method.ItemClick);setListener(field,viewInject.itemLongClick(),Method.itemLongClick);AbIocSelect select = viewInject.select();if(!TextUtils.isEmpty(select.selected())){setViewSelectListener(field,select.selected(),select.noSelected());}}} catch (Exception e) {e.printStackTrace();}}}}
其實就是通過反射讓我們可以使用註解來聲明view控制項,省去繁瑣的findviewbyId,比如我們之前要用id為tv_name的textview,要這樣寫
TextView name;name = (TextView)(findViewById(R.id.tv_name));
而現在我們只需要用註解聲明一下就ok了
@AbIocView(id=R.id.tv_name)TextView name;
這和很多的註解架構是一樣的道理,不過在這裡我們就看到了註解底層的實現原理,是不是一下子頓悟了,當然這裡用到了反射機制和自訂註解,所以對於一些初學者還是建議先去看看這方面的知識,我們來看AbIocView的源碼,就是自訂的註解,
@Target(ElementType.FIELD) //作用於屬性@Retention(RetentionPolicy.RUNTIME) //編譯器將annotation儲存於class中<span style="color: rgb(103, 102, 21); font-family: ‘Hiragino Sans GB W3‘, ‘Hiragino Sans GB‘, Arial, Helvetica, simsun, u5b8bu4f53; font-size: 16px; line-height: 28px; "> </span>public @interface AbIocView {public int id(); //屬性必須,其他可以不指定,因為有預設值public String click() default "";public String longClick() default "";public String itemClick() default "";public String itemLongClick() default "";public AbIocSelect select() default @AbIocSelect(selected="") ;}
AbIocSelect類似,大家就自己去看吧就當是鞏固上面學到的東西了,然後在剛才的initIocView中有這麼個方法setListener,就是根據AbIocView那幾個方法設定監聽器,相信大家肯定能看懂,這裡我就不說了
openMonitor和closeMonitor就先不說了,一般也用不到(其實是我還沒有看到那裡),再然後就沒有然後了吧,ok,今天的分析就到這裡,若有錯誤,敬請提出,大家交流學習,共同進步---〉
睡覺qu,累死了
安卓andbase架構源碼解讀( 一)