以下内容為原創,歡迎轉載,轉載請注明
AndroidInject項目是我寫的一個使用注解注入來簡化代碼的開源項目
<a href="https://github.com/wangjiegulu/androidInject">https://github.com/wangjiegulu/androidInject</a>
今天新增功能如下:
1. 增加@AIScreenSize注解,作用于屬性,用于注入目前裝置的螢幕大小(寬高)
2. 增加對網絡請求的支援,使用動态代理實作:@AIGet注解,作用于接口方法,表示以GET來請求url;@AIPost注解,作用于接口方法,表示以POST來請求url;@AIParam,用于注入請求參數
3. 增加@AINetWorker注解,作用于屬性,用于注入網絡請求服務
4. 增加GET或POST請求時請求參數可使用Params類傳入,簡化代碼
主要執行代碼如下:
用@AINetWorker注解注入NetWorker接口的子類代理(動态代理模式):
然後啟動線程,線上程中調用進行網絡請求:
請求的結果封裝在RetMessage類中(AndroidInject架構所作的事就是執行Get或者Post請求,獲得傳回結果,然後json解析後封裝在RetMessage中):
接下來看下PersonWorker接口中所作的事情:
PersonWorker是自己寫的一個接口(以後需要有新的網絡請求,都可以類似編寫Worker),聲明了執行網絡請求的各種方法,這些方法需要加上@AIGet或者@AIPost注解,用于聲明請求方式,并在此注解中的value()值設定為所要請求的url(此注解的其他屬性後續會陸續擴充)
方法的@AIParam注解是作用與mybatis的@Param注解類似,可以設定請求攜帶的參數
如果參數比較多,則推薦使用Params來存放參數,以此來簡化代碼,Params類實質上就是一個HashMap,存放參數的鍵值對即可。
接下來分析下架構是怎麼實作的,其實上面講過,主要是用Annotaion和動态代理了
首先看看PersonWorker的注入,在AIActivity(AIActivity,AndroidInject開源項目中的Activity使用注解的話,你寫的Activity必須繼承AIActivity,另外如果要使用FragmentActivity,則需要繼承AISupportFragmentActivity)啟動時,首先會去解析添加的注解,這裡讨論@AINetWorker注解,内部代碼很簡單:
通過代碼可知,是使用反射來實作的,主要的代碼是這句:
這句代碼的作用是通過Class獲得一個PersonWorker實作類的代理對象,這裡很明顯是使用了動态代理。
是以,最核心的類應該是NetInvoHandler這個類,這個類的代碼如下(篇幅問題,是以就折疊了):

View Code
裡面的代碼還沒有好好的重構,是以,看起來會更直白,該類實作了InvocationHandler,很明顯的動态代理。
我們通過NetInvoHandler的getWorker靜态方法,來擷取一個指定Class的Worker實作類的代理對象,由于實際應用時,Worker接口應該會很多,為了不重複生成相同Worker實作類的代理對象,是以這裡在生成一個後,儲存起來,確定一個Worker隻生成一個代理對象,一個NetInvoHandler。
這裡有個地方需要注意一下,以前使用的動态代理,需要一個RealSubject,也就是真實對象,是Worker的實作類。這樣,在invoke方法中就可以調用真實對象的對應方法了,但是現在,進行網絡請求,我們沒有去寫一個類然後實作PersonWorker接口,因為沒有必要,我們完全可以在invoke方法中去執行相同的網絡請求。
請想下,之是以需要架構的存在 不就是為了把一些模闆的東西給簡化掉麼?現在的網絡請求這些步驟就是一些模闆話的東西,我們需要的就是調用方法,自動進行網絡請求(架構做的事),然後傳回給我結果。是以網絡請求這一步,寫在invoke方法中即可。
而不是所謂的編寫一個類,實作PersonWorker接口,在這個實作類中進行網絡請求,然後在invoke方法中調用真實對象的對應該方法。
是以,在Proxy.newProxyInstance的interfaces中填寫需要實作的接口,也就是現在的PersonWorker。
接下來看下invoke中做的事情,首先根據方法增加的注解來識别是GET請求還是POST請求。然後各自執行請求(因為我請求的執行,寫在NetWork中了,這裡直接傳回了請求結果字元串StringBuilder sb)。
接下來,使用Gson這個霸氣的工具,一鍵從json解析封裝成RetMessage對象。(是以,這裡是需要Gson庫的支援,大家網上下載下傳gson.jar,或者使用maven)
當然,要使用Gson一鍵解析封裝的前提是伺服器端的編寫需要儲存一緻性,下面是我伺服器端測試的代碼:
伺服器端傳回結果時,也是封裝在RetMessage類中,這個類伺服器端和用戶端是保持一緻的,是以可以一鍵轉換。
如果你在開發的過程中,RetMessage類中封裝的東西不能滿足你的需求,可以自己編寫結果類,當然在Worker中聲明方法中傳回值就應該是你寫的結果類了。
到此為止,講解完畢
另:如果,你需要寫一個查詢User資訊的網絡請求,應該怎麼寫?
隻需編寫UserWorker接口,然後聲明方法findUsers(),寫上@AIGet或者@AIPost注解,寫明url和請求參數。然後通過@AINetWorker注解注入userWorker,然後開啟線程,調用userWorker的findUsers()方法即可。
當然UserWorker也可以不使用注解獲得,而是調用“NetInvoHandler.getWorker(UserWorker.class)”獲得!