2017安卓主流框架搭建迄沫?看這篇就夠了(下)

四.mvp模式(使用MVPPluge插件稻扬,自動生成MVP的類文件以及該插件的改裝)

MVP模式理解起來很容易,結(jié)合安卓羊瘩,簡單概括:無非就是在activty中將網(wǎng)絡(luò)請求等與數(shù)據(jù)相關(guān)的操作封裝到一個(gè)P類中泰佳,activty中持有P的引用,同時(shí)P中又包含activty中調(diào)度View的一些方法尘吗,這樣activity中只寫業(yè)務(wù)邏輯逝她,請求獲取數(shù)據(jù)全靠P去實(shí)現(xiàn),好處是在請求很多睬捶,業(yè)務(wù)邏輯復(fù)雜的情況下整個(gè)activity的代碼依然清晰黔宛,同時(shí)activity的職責(zé)也更單一。

曾經(jīng)看到過一句話擒贸,大致的意思是:

"代碼的規(guī)范臀晃,業(yè)務(wù)邏輯的清晰,類之間的解耦等等一定是通過增加而不是減少代碼來實(shí)現(xiàn)的酗宋』蹋”

同樣,mvp的問題也就暴露出來了蜕猫,要實(shí)現(xiàn)activity中模塊的分離寂曹,需要增加P類,需要實(shí)現(xiàn)各種接口回右,因此隆圆,之前的項(xiàng)目中一直未使用mvp,都是在activity中寫到底翔烁,最多就是抽取一些方法到util渺氧,helper等類中。
這回雖然引入了mvp蹬屹,但是實(shí)際方法中同樣也是分情況來看侣背,如果要實(shí)現(xiàn)的功能很簡單白华,或者功能很邊緣化,甚至小迭代時(shí)間緊贩耐,任務(wù)重的時(shí)候還是直接activity中操作數(shù)據(jù)弧腥,只有在一些比較重要,核心的模塊里 通過mvp來做更優(yōu)雅的實(shí)現(xiàn)潮太。
題外話到此管搪,下面重點(diǎn)來說說這次項(xiàng)目搭建中mvp的使用過程。

使用過程:

1.android studio引用 MVPPlugin插件
2.MVPPlugin插件的使用
3.MVPPlugin插件的改造

可以看到這里mvp模式都是圍繞一個(gè)“ MVPPlugin插件”的東西铡买,這個(gè)插件是干嘛的更鲁? 其實(shí)就是一個(gè)幫助開發(fā)者一鍵生成mvp模式所需要的一些接口類,P類等奇钞。具體的使用方法可以看看這個(gè)

http://mp.weixin.qq.com/s/fo34hyvjzNSURSh_V8y4oQ

如果你之前也只是聽說并未真正使用過mvp模式開發(fā)澡为,那么這個(gè)插件將極大的節(jié)約你的mvp上手的時(shí)間成本,基本屬于拿來就用蛇券。 不過用歸用缀壤,插件幫你生成的那些類的源碼還是要好好看看,特別是基類纠亚,做到消化吸收塘慕!可能自己暫時(shí)寫不出來,但起碼要理解原理蒂胞。

五.網(wǎng)絡(luò)框架的接入(RXJava2+Retrofit2.0+OKHTTP)

這三個(gè)玩意兒無疑是目前灰惩寄兀火的項(xiàng)目,但凡做android開發(fā)骗随,可以說不一定用過蛤织,但絕對都聽過,了解過鸿染。

Rxjava:

是個(gè)很神奇的東西指蚜。網(wǎng)上的描述一大堆:什么 事件流推動,響應(yīng)式編程涨椒,觀察訂閱等等 我剛接觸的時(shí)候百度了半天摊鸡,也沒弄清楚到底是個(gè)啥,使用有啥好處蚕冬,直到看到這篇文章免猾,
我將作者稱為“管神”,水管的管囤热。

http://www.reibang.com/u/c50b715ccaeb([給初學(xué)者的RxJava2.0教程)

哈哈 有一個(gè)系列猎提,幫助上手Rxjava,但實(shí)際上你可能會跟我一樣旁蔼。 系列文章看了一遍锨苏,感覺懂了疙教,但是想在項(xiàng)目里面用,發(fā)現(xiàn)用不上蚓炬。
然后結(jié)合Retrofit2.0+OKHTTP直接先在項(xiàng)目里面用起來松逊,用熟練了再把文章看一遍,哦肯夏,恍然大悟-事件推動。
說得好像有點(diǎn)云里霧里犀暑,先別噴我驯击,咋先用上再說。

Retrofit2.0:

是個(gè)很方便的東西耐亏,說它方便徊都,是因?yàn)樗褚粋€(gè)接口,本身沒有實(shí)現(xiàn)广辰,沒有功能暇矫,但是你把Gson框架放進(jìn)去,它就能json解析择吊,你把OKHTTP放進(jìn)去它就能發(fā)送網(wǎng)絡(luò)請求李根,你把Rxjava放進(jìn)去它就能進(jìn)行發(fā)送事件流。
那么整個(gè)的連接起來是神馬几睛?
RXJava2+Retrofit2.0+OKHTTP+GSON=“發(fā)送 網(wǎng)絡(luò)請求 并自動解析json數(shù)據(jù)的事件流”
可能你會說了房轿,作者你又裝X,神馬框架不能發(fā)送網(wǎng)絡(luò)請求所森,然后解析json數(shù)據(jù)囱持?
但我會告訴你,這個(gè)X我裝定了焕济!重點(diǎn)是“事件流”三個(gè)字》鬃保現(xiàn)在你給我0分,等你把上面推薦的rxjava文章看完理解之后或許你會重新打出97分晴弃。
為了增加說服力掩幢,這里我給出一個(gè)復(fù)雜的場景:

同時(shí)壓縮兩張圖片,都壓縮成功后調(diào)用上傳接口肝匆,并將上傳接口返回的部分?jǐn)?shù)據(jù)作為參數(shù)粒蜈,請求另外一個(gè)接口。

這個(gè)需求涉及的東西還不少旗国,圖片壓縮枯怖,線程變換,網(wǎng)絡(luò)請求嵌套能曾。如果不用rxjava度硝,可能最常規(guī)的方法應(yīng)該是這樣:
開兩個(gè)子線程壓縮圖片肿轨,handler發(fā)送成功信號到主線程,while循環(huán)等待蕊程,兩個(gè)標(biāo)識都成功然后發(fā)送網(wǎng)絡(luò)請求椒袍,請求成功回調(diào)再嵌套一個(gè)請求。
上面的實(shí)現(xiàn)基本上能滿足這個(gè)需求藻茂,但是無論從代碼量驹暑,代碼可讀性等等而言都不是那么優(yōu)雅,但是如果采用rxjava辨赐,利用它自帶的線程切換优俘,操作符zip,事件流轉(zhuǎn)換flatMap的話掀序,你可以寫出一段邏輯清晰帆焕,代碼量少的鏈?zhǔn)酱a,不恭,叶雹,,换吧,
好吧折晦,可能這樣描述無法達(dá)到那種 “聽到后連我自己都害怕”的效果,式散,但是筋遭,請相信,暴拄,效果真的很牛X漓滔,誰用誰知道。

基本使用:

1.初始化一個(gè)OkHttpClient

  OkHttpClient  mOkHttpClient = new OkHttpClient.Builder()
            .readTimeout(DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.SECONDS)
            .writeTimeout(DEFAULT_WRITE_TIMEOUT_MILLIS, TimeUnit.SECONDS)
            //設(shè)置連接超時(shí)時(shí)間
            .connectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.SECONDS)
            //設(shè)置緩存
            .cache(getDefaultCache())
            //日志攔截器
            .addInterceptor(loggingInterceptor)
            //頭部攔截器
            .addInterceptor(new HeadsInterceptor())
            //設(shè)置SSH 兼容https
            .sslSocketFactory(sslSocketFactory.sSLSocketFactory, sslSocketFactory.trustManager)
            //默認(rèn)全部信任
            .hostnameVerifier(SSHUtil.getHostnameVerifier())
            .build();

2.通過Retrofit.Builder初始化一個(gè)RetrofitApi對象乖篷,過程中設(shè)置請求代理(就是前面mOkHttpClient )响驴,設(shè)置數(shù)據(jù)解析,設(shè)置Rxjaxa

 Retrofit.Builder builder = new Retrofit.Builder()
            //設(shè)置網(wǎng)絡(luò)請求實(shí)現(xiàn)
            .client(mOkHttpClient)
            //設(shè)置json數(shù)據(jù)解析實(shí)現(xiàn)
            .addConverterFactory(GsonConverterFactory.create())
            //RXJAVA適配器
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create());

    //這里主域名的設(shè)置單獨(dú)來弄撕蔼,萬一后臺奇葩豁鲤,一個(gè)app里兩個(gè)主域名的話可以再建一個(gè)API_X的接口類,這里類似的單獨(dú)再配置他的baseurl
   RetrofitApi  httpApi = builder.baseUrl(Constants.APP_HOST)
            .build()
            .create(RetrofitApi.class);

    //配置了RxJava2CallAdapterFactory即集合RXjava的話httpApi調(diào)用xxx方法可以直接返回Observable鲸沮,然后拿來subscribe
    //不結(jié)合RXjava的話返回httpApi調(diào)用xxx方法返回Call對象琳骡,然后拿來enqueue發(fā)請求

    //結(jié)合RXjava的優(yōu)點(diǎn):更靈活,鏈?zhǔn)秸{(diào)用讼溺,線程切換方便楣号,各種操作符效果吊炸天。 說白了就是可以在處理很復(fù)雜嵌套循環(huán)請求的時(shí)候利用RXJAVA,簡化開發(fā)
    //不過RXJAVA自身的學(xué)習(xí)成本的確是個(gè)問題炫狱,我到現(xiàn)在也是云里霧里藻懒,不過既然是框架,视译,嬉荆,先用再說啦!

3.調(diào)用RetrofitApi實(shí)例里的業(yè)務(wù)接口并處理回調(diào)

  httpApi.getIndexData().subscribe(new Observer<TDataBean<IndexMultBean>>() {
        @Override
        public void onSubscribe(Disposable d) {
            
        }

        @Override
        public void onNext(TDataBean<IndexMultBean> value) {

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
    })
全局封裝說明:

真正使用過程中肯定不會每次請求都重復(fù)上面過程酷含,都會做封裝鄙早,這里是給出的封裝實(shí)例,可能并不完美第美,歡迎批評指出哈蝶锋!

三個(gè)類,分別是:
HttpUtil:初始化retrofit什往,并根據(jù)服務(wù)器主域名生成一個(gè)全局的 RetrofitApi對象
RetrofitApi: 注解的方式定義出具體的業(yè)務(wù)接口
ApiManager:網(wǎng)絡(luò)請求發(fā)起類,通過獲取HttpUtil中的retrofit實(shí)例慌闭,調(diào)用retrofit中定義的業(yè)務(wù)接口并傳入?yún)?shù)别威。

在MVP模式的Presenter 里調(diào)用方式如下:

public class LoginPresenter extends BasePresenterImpl<LoginContract.View> implements LoginContract.Presenter {
private void textHttp() {
    ApiManager.login("acount","pwdString").subscribe(new HttpObserver<TDataBean<UserInfo>>(mView) {
        @Override
        public void onSucceed(TDataBean<UserInfo> value) {

        }

        @Override
        public void onDefeat(TDataBean<UserInfo> value) {
            super.onDefeat(value);
        }
    });
}

}

HttpObserver繼承自O(shè)bserver<T>,對請求結(jié)果做了進(jìn)一步的封裝驴剔,具體見源碼

部分源碼展示:

1.添加引用依賴

 //OKhttp
compile 'com.squareup.okhttp3:okhttp:3.9.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.7.0'
 //retrofit
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
//rxjava
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

2.請求模塊初始化

public class HttpUtil {
//超時(shí)時(shí)間
private static final long DEFAULT_READ_TIMEOUT_MILLIS = 20;//提交數(shù)據(jù)超時(shí)時(shí)間
private static final long DEFAULT_WRITE_TIMEOUT_MILLIS = 20;//提交數(shù)據(jù)超時(shí)時(shí)間
private static final long DEFAULT_CONNECT_TIMEOUT_MILLIS = 10;//請求超時(shí)時(shí)間
//緩存大小
private static final long HTTP_RESPONSE_DISK_CACHE_MAX_SIZE = 10 * 1024 * 1024;
//OkHttpClient
private OkHttpClient mOkHttpClient;
//API接口
private RetrofitApi httpApi;

private HttpUtil() {
    initOKHttp();
    initRetrofit();
}

public static HttpUtil getInstance() {
    return ClassHolder.instace;
}

private static class ClassHolder {
    static final HttpUtil instace = new HttpUtil();
}

private void initOKHttp() {
    //日志攔截器省古,專業(yè)處理請求過程中的日志 ,header、body數(shù)據(jù)
    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
    //根據(jù)包的類型控制日志輸出與否
    loggingInterceptor.setLevel(BasePackageUtil.isApkDebugable() ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE);

    //SSH相關(guān)設(shè)置丧失,處理https請求的豺妓,默認(rèn)全部信任,不添加的話遇到https請求可能會出異常布讹,WebView琳拭,Picasso,Gilde等框架都會有此問題
    SSLParams sslSocketFactory = SSHUtil.getSslSocketFactory();

    mOkHttpClient = new OkHttpClient.Builder()
            .readTimeout(DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.SECONDS)
            .writeTimeout(DEFAULT_WRITE_TIMEOUT_MILLIS, TimeUnit.SECONDS)
            //設(shè)置連接超時(shí)時(shí)間
            .connectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.SECONDS)
            //設(shè)置緩存
            .cache(getDefaultCache())
            //日志攔截器
            .addInterceptor(loggingInterceptor)
            //頭部攔截器
            .addInterceptor(new HeadsInterceptor())
            //設(shè)置SSH 兼容https
            .sslSocketFactory(sslSocketFactory.sSLSocketFactory, sslSocketFactory.trustManager)
            //默認(rèn)全部信任
            .hostnameVerifier(SSHUtil.getHostnameVerifier())
            .build();


}

private void initRetrofit() {
    Retrofit.Builder builder = new Retrofit.Builder()
            //設(shè)置網(wǎng)絡(luò)請求實(shí)現(xiàn)
            .client(mOkHttpClient)
            //設(shè)置json數(shù)據(jù)解析實(shí)現(xiàn)
            .addConverterFactory(GsonConverterFactory.create())
            //RXJAVA適配器
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create());

    //這里主域名的設(shè)置單獨(dú)來弄描验,萬一后臺奇葩白嘁,一個(gè)app里兩個(gè)主域名的話可以再建一個(gè)API_X的接口類,這里類似的單獨(dú)再配置他的baseurl
    httpApi = builder.baseUrl(Constants.APP_HOST)
            .build()
            .create(RetrofitApi.class);

    //配置了RxJava2CallAdapterFactory即集合RXjava的話httpApi調(diào)用xxx方法可以直接返回Observable膘流,然后拿來subscribe
    //不結(jié)合RXjava的話返回httpApi調(diào)用xxx方法返回Call對象絮缅,然后拿來enqueue發(fā)請求

    //結(jié)合RXjava的優(yōu)點(diǎn):更靈活,鏈?zhǔn)秸{(diào)用呼股,線程切換方便耕魄,各種操作符效果吊炸天。 說白了就是可以在處理很復(fù)雜嵌套循環(huán)請求的時(shí)候利用RXJAVA彭谁,簡化開發(fā)
    //不過RXJAVA自身的學(xué)習(xí)成本的確是個(gè)問題吸奴,我到現(xiàn)在也是云里霧里,不過既然是框架,奄抽,蔼两,先用再說啦!

}

public OkHttpClient getmOkHttpClient() {
    return mOkHttpClient;
}

public RetrofitApi getHttpApi() {
    return httpApi;
}

public Cache getDefaultCache() {
    String dir = BaseFileUtil.getHttpCacheDir();
    File file = new File(dir);
    Cache cache = new Cache(file, HTTP_RESPONSE_DISK_CACHE_MAX_SIZE);
    return cache;
}

}

3.API封裝與調(diào)用

public interface RetrofitApi {
/*獲取首頁數(shù)據(jù)*/
@POST(Constants.FUNCTION_INDEX)
Observable<TDataBean<IndexMultBean>> getIndexData();

/*登錄*/
@POST(Constants.FUNCTION_LOGIN)
Observable<TDataBean<UserInfo>> login(@Body JsonObject object);
}

public class ApiManager {
//統(tǒng)一設(shè)置線程
private static <T> Observable<T> subscribeOn(Observable<T> observable) {
    return observable.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread());
}
//獲取RetrofitApi實(shí)例
private static RetrofitApi getJavaApi() {
    return HttpUtil.getInstance().getHttpApi();
}

/***************************************業(yè)務(wù)邏輯接口**************************************/
    /*獲取首頁數(shù)據(jù)*/
public static Observable<TDataBean<IndexMultBean>> getIndexData() {
    Observable<TDataBean<IndexMultBean>> observable = getJavaApi().getIndexData();
    return subscribeOn(observable);
}

/*獲取首頁數(shù)據(jù)*/
public static Observable<TDataBean<UserInfo>> login(String username, String pwd) {
    JsonObject data = new JsonObject();
    data.addProperty("mobile", username);
    data.addProperty("password", pwd);
    data.addProperty("device_token", DeviceUtils.getDeviceId());
    Observable<TDataBean<UserInfo>> observable = getJavaApi().login(data);
    return subscribeOn(observable);
}
}

完整的demo地址:
https://gitee.com/lunguoguo/revised_development_framework.git (已更新)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逞度,一起剝皮案震驚了整個(gè)濱河市额划,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌档泽,老刑警劉巖俊戳,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異馆匿,居然都是意外死亡抑胎,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門渐北,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阿逃,“玉大人,你說我怎么就攤上這事赃蛛∈扬保” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵呕臂,是天一觀的道長破托。 經(jīng)常有香客問我,道長歧蒋,這世上最難降的妖魔是什么土砂? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮谜洽,結(jié)果婚禮上萝映,老公的妹妹穿的比我還像新娘。我一直安慰自己褥琐,他們只是感情好锌俱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著敌呈,像睡著了一般贸宏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上磕洪,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天吭练,我揣著相機(jī)與錄音,去河邊找鬼析显。 笑死鲫咽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播分尸,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼锦聊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了箩绍?” 一聲冷哼從身側(cè)響起孔庭,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎材蛛,沒想到半個(gè)月后圆到,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡卑吭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年芽淡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豆赏。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挣菲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出掷邦,到底是詐尸還是另有隱情己单,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布耙饰,位于F島的核電站,受9級特大地震影響纹份,放射性物質(zhì)發(fā)生泄漏苟跪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一蔓涧、第九天 我趴在偏房一處隱蔽的房頂上張望件已。 院中可真熱鬧,春花似錦元暴、人聲如沸篷扩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鉴未。三九已至,卻和暖如春鸠姨,著一層夾襖步出監(jiān)牢的瞬間铜秆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工讶迁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留连茧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像啸驯,于是被迫代替她去往敵國和親客扎。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容