又是一個MVP+RxJava+Retrofit的干貨集中營

歡迎訪問我的個人博客训唱,原文鏈接:http://wensibo.top/2017/05/15/GankClient/ 玫霎,未經(jīng)允許不得轉發(fā)凿滤!

Google_I/O_2017

前言

今天想要與大家一起分享的是近一個星期內(nèi)開發(fā)的一個新app——干貨集中營客戶端妈橄,其實網(wǎng)上已經(jīng)有許多類似的項目,代碼家也在他的干貨集中營中推薦了幾款優(yōu)秀的作品翁脆,我也借鑒了其中的一些眷蚓,自己開發(fā)出一款干貨集中營客戶端,目前項目已經(jīng)發(fā)布到github反番,如果你想了解整個工程的具體內(nèi)容沙热,那么你可以fork或者clone,如果你覺得我做得還可以罢缸,那么請你賜給我一個star唄篙贸!你的支持會是我努力的動力。
慢慢的已經(jīng)養(yǎng)成了每篇文章都會來一個前言祖能,也慢慢地將寫文章潛移默化的轉變成寫故事歉秫,所以每個故事都會有前言,也都會有結果养铸,這次也不例外雁芙。
距離上篇引起熱烈反響的文章發(fā)布已經(jīng)過去一個月了,承蒙廣大網(wǎng)友對我的支持以及建議钞螟,當然作為一個90后兔甘,我也很虛心的接受來自各方的吐槽,畢竟我并不優(yōu)秀鳞滨,只是一直在優(yōu)秀的路上努力的奔跑著洞焙。下面我想跟大家一起分享一下這一個月里我做了些什么事,以及接下來一段時間的計劃和打算拯啦。

Have Done List

  • 持續(xù)22天在github上出現(xiàn)澡匪,看看下面這棵貢獻樹
    contributions
  • 博客瀏覽量突破35000
    blog
  • 看了1本好書——《網(wǎng)絡是怎樣連接的》
  • 研究Retrofit與RxJava的源碼(待我葡萄成熟時再把文章放出來吧,現(xiàn)在太嫩了褒链,不好意思讓大家看到)
  • 2次擔任演講的主講人(之后會寫一篇文章講述我的演講技巧)
  • 看了錘子科技新品發(fā)布會(我是羅粉但也是加油唁情,心疼老羅一秒)
  • 努力尋找實習(投了許多簡歷,但是無一幸免:sob: ,有同學可以推薦一波嗎甫匹?沒有的話我待會再問問)
  • 1個全新的干貨集中營客戶端app(也是寫這篇文章的緣由)

Todo List

  • Google I/O 2017開發(fā)者大會
  • xposed插件開發(fā)(這個閃念是有一天夜里驚醒過來的想法)
  • 繼續(xù)寫好的文章與大家一起分享甸鸟,不僅僅是技術方面的,還有許多我覺得有用的文章兵迅,都會為大家奉上抢韭,感謝老鐵們的支持
  • 繼續(xù)看書
  • 繼續(xù)找實習(嗚嗚嗚~~~(>_<)~~~,體會到工作難找了,尤其是互聯(lián)網(wǎng)寒冬)

老鐵別廢話了

好啦恍箭,上面講了一大堆廢話終于可以進入正題了刻恭,我也很基動,開車咯扯夭!

項目介紹

logo

GankClient(又稱干貨集中營客戶端)是一個全新的干貨集中營客戶端吠各,它獲取的是來自干貨集中營API的數(shù)據(jù)臀突,利用全新的Material Design的設計語言展示數(shù)據(jù)內(nèi)容。整個項目采用MVP的設計架構贾漏,并且大量使用RxJava2候学,網(wǎng)絡框架使用的是Retrofit。我用下面幾個裝逼的句子來形容一下這個APP:

  • 更快速的加載速度
  • 更流暢的頁面體驗
  • 更有趣的刷新效果
  • 更精美的網(wǎng)頁瀏覽
  • 更美觀的視覺享受

這個只是我的個人感受纵散,大神請輕噴:joy: 梳码,不過還是希望大家能夠喜歡這個項目,并且積極的向我pull request以及反饋bug伍掀,希望大家多多支持掰茶。如果可以的話給個star咯。

預覽

誰說不給圖的

全部效果圖來一發(fā)

screenshot
screenshot
screenshot

screenshot
screenshot
screenshot

沒有gif圖都不好意思說話了

gif
gif

下載

如果你想測試這個項目蜜笤,那么請手動clone濒蒋,如果你想嘗試一下APP,那么你可以使勁戳這里 ,或者掃下面的二維碼把兔。后期我會發(fā)布到應用市場沪伙,希望大家可以多多支持!

QRCode

功能&特色

加醋的表示已經(jīng)實現(xiàn)县好,沒有加粗的表示尚未實現(xiàn)或者仍需改善的功能

  • 實時獲取服務器的最新數(shù)據(jù)围橡,采用CardView的布局以更好的展現(xiàn)數(shù)據(jù)。
  • 刷新效果很好玩缕贡,真的很精致翁授,感謝Phoenix
  • 如果你裝有Chrome瀏覽器晾咪,并將其設置為默認瀏覽器收擦,那么你的網(wǎng)頁瀏覽效果就會十分酷炫。感謝Custom-Tabs-Client ! 墻裂推薦Chrome谍倦,如果你沒有安裝Chrome炬守,那也沒關系,那就用傳統(tǒng)的WebView吧剂跟!
  • 更加統(tǒng)一的過渡動畫,相信你會愛上它酣藻。
  • 保存曹洽、分享圖片與鏈接,也可以直接使用瀏覽器打開鏈接辽剧。
  • **更好看的Material Design設計風格送淆。 **
  • **妹子很漂亮喲! **
  • 優(yōu)化webview的視頻播放怕轿。
  • 增加使用系統(tǒng)瀏覽器的選項偷崩。
  • 修復在主界面中加載數(shù)據(jù)到2016/4/20左右時數(shù)據(jù)顯示錯亂的問題辟拷。
  • 增強分享功能。

分解

終于到了這個純干貨步驟了阐斜,別說話先看東西衫冻!

如何使用MVP的設計架構

我先展示以下這個項目的結構圖,讓大家心里有個底

  • http
    • GankRetrofit.java
    • GankRetrofitClient.java
  • mvp
    • model
      • BaseModel.java
    • presenter
      • BasePresenter.java
    • view
      • IBaseView.java
  • ui
    • activity
    • adapter
    • base
    • chromeviews
    • fragment
    • widget

可以看到谒出,整個項目的結構還算比較清晰隅俘,整體的架構都是在mvp目錄中定下來的,mvp架構分三層笤喳,model模型層为居,用于定義一些數(shù)據(jù)的類型;presenter呈現(xiàn)者層杀狡,用于處理view層的邏輯蒙畴;view顯示層,這里定義的都是接口呜象,真正實現(xiàn)他們的是activity膳凝,這些activity只要實現(xiàn)相應的接口,就能夠自己復寫其中的方法董朝。
當然我這么說你肯定還是一臉懵逼鸠项,而且我還必須跟你說,我這個不算最純粹的MVP模式子姜,最純粹的寫法應該都是面向接口編程的祟绊,就是在model,presenter哥捕,以及view下都是定義接口牧抽,而到了具體的運用場景,就定義出具體的類去實現(xiàn)這些接口遥赚。當然了扬舒,為了讓大家能夠更清楚MVP是怎么實現(xiàn)的,下面我會用代碼的形式為大家展示凫佛,例如我要編寫MainActivity的代碼讲坎,首先已經(jīng)知道在這個Activity中需要做如下這些事:

  • 初始化組件
  • 加載Fragment
  • FloatingActionButton的點擊事件——去到DailyActivity
  • drawer menu的點擊事件——去到AboutActivity

為了讓Activity專注于界面的工作,而不用去考慮邏輯處理的操作愧薛,這個就是所謂的解耦晨炕,那么我們可以將邏輯的操作放到presenter中去,而與界面有關的操作就放在view下毫炉,于是我們就可以這樣寫(為了便于大家理解瓮栗,我將項目中的代碼做了適當?shù)男薷模绻阆肓私飧泳唧w的邏輯,可以仔細看看代碼):

  • IBaseView
public interface IBaseView {
        //界面初始化操作
        void init();
}
  • BasePresenter&MainPresenter
/**
* 將presenter的公共操作集成為BasePresenter
*/
public abstract class BasePresenter <T extends IBaseView>{
        protected Disposable disposable;
        protected Context context;
        protected T iView;      //獲取到view的對象

        public BasePresenter(Context context, T iView) {
                this.context = context;
                this.iView = iView;
        }

        public void init() {
                iView.init();
        }

        public abstract void release();
        public abstract void initPresenter();
}

/**
* 每一個界面都可以編寫自己的Presenter费奸,并指定View的泛型
*/
public class MainPresenter extends BasePresenter<IBaseView> {

        public MainPresenter(Context context, IBaseView iView) {
                super(context, iView);
        }

        @Override
        public void release() {

        }

        public void toDailyActivity() {
                Intent intent = new Intent(context, DailyActivity.class);
                context.startActivity(intent);
        }

        public void toAboutActivity() {
                Intent intent = new Intent(context, AboutActivity.class);
                context.startActivity(intent);
        }

        public void toSettingActivity() {
                Intent intent = new Intent(context, SettingActivity.class);
                context.startActivity(intent);
        }
  • MainActivity
public class MainActivity <MainPresenter> extends AppCompatActivity implements IBaseView{

        @OnClick(R.id.fab_main)
        void fabClick() {
                presenter.toDailyActivity();
        }

        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
        }


        @Override
        protected void initPresenter() {
                presenter = new MainPresenter(this, this);
                presenter.init();
        }

        @Override
        public void init() {
                //所有的初始化操作
        }

        @Override
        protected void onDestroy() {
                super.onDestroy();
                presenter.release();
        }

}

大概就是這樣一個套路弥激,講真我這樣講你肯定迷糊,我當初在學這個的時候也是十分凌亂愿阐,后來才發(fā)現(xiàn)只有自己動手親自敲代碼才能了解整個思路微服,另外大家在學習MVP的過程中應該擅于畫圖,不管是在紙上畫還是使用思維導圖都行换况,這樣可以讓你更加宏觀的了解整個調(diào)用的順序以及各個類之間的關系职辨,這絕不是你看了一篇文章就能懂的。

你真的用好RxJava了嗎

當我問這個問題的時候戈二,其實我想說的是RxJava的用處很廣舒裤,我們想當然的認為只要RxJava與Retrofit相配合就算是完成任務了,但實際上只要涉及到耗時操作觉吭、線程切換:網(wǎng)絡請求腾供、圖片解析、數(shù)據(jù)庫讀取等等需要用多個線程一起完成的工作時鲜滩,你都可以用到RxJava伴鳖,并且如果你還一直用RxJava1的話,那么你也OUT啦徙硅,當你認識RxJava2.x的時候你會發(fā)現(xiàn)他更強大了榜聂。關于RxJava,我后續(xù)會寫相關的文章與大家一起分享嗓蘑,這里我舉項目中遇到的一個例子须肆,看看RxJava的用武之地是多么的廣:

/**
* 將圖片保存在本地
*/
public void openWebView(final Gank gank) {
    disposable=Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(@NonNull ObservableEmitter e) throws Exception {
                    e.onNext(android.R.drawable.ic_menu_share);
            }
    }).subscribeOn(Schedulers.newThread())//開啟一個新線程來進行耗時操作
            .map(new Function<Integer, Bitmap>() {
                    @Override
                    public Bitmap apply(@NonNull Integer integer) throws Exception {
                            //將資源id解析為bitmap是一個耗時操作
                            return BitmapFactory.decodeResource(activity.getResources(), integer);
                    }
            }).observeOn(AndroidSchedulers.mainThread())//回到主線程操作bitmap
            .subscribe(new Consumer<Bitmap>() {
                    @Override
                    public void accept(@NonNull Bitmap bitmap) throws Exception {
                            //拿到bitmap之后做的界面更新
                    }
            });
}
        
//釋放資源
public void release() {
                if (disposable != null&&!disposable.isDisposed()) {
                        disposable.dispose();
                }
        }

爽快的Retrofit

還記得之前我寫過Volley的一系列文章,雖然覺得這個開源框架已經(jīng)不錯了桩皿,但畢竟長江后浪推前浪豌汇,在Retrofit的面前,Volley簡直就是小巫見大巫泄隔,看看我們應該如何在項目中使用:

  • 1拒贱、新建一個接口,用注解的形式在里面定義網(wǎng)絡請求的方法:
public interface GankRetrofit {
        //獲取MainActivity界面的數(shù)據(jù)佛嬉,具體的請求路徑應該詳細看官方的API說明逻澳,
        // Retrofit與RxJava配合之后才能顯示出更強的威力
        @GET("data/{type}/40/{page}")
        Observable<MainData> getMainData(@Path("type") String type, @Path("page") int page);
}
  • 2、獲得實例:
Gson date_gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").create();
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://gank.io/api/")         //指定服務器地址
        .addConverterFactory(GsonConverterFactory.create(date_gson))    //添加一個gson的解析器
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())          // 如果想使用RxJava那就需要添加這個適配器  
        .build();
GankRetrofit gankRetrofit;
gankRetrofit = retrofit.create(GankRetrofit.class);            //獲取GankRetrofit的對象
  • 3暖呕、獲取數(shù)據(jù):
//返回的Observable<MainData>對象就可以使用RxJava進行解析了
gankRetrofit.getMainData("Android",40);

更好的網(wǎng)頁瀏覽體驗——Custom-Tabs-Client

如果你使用過Chrome瀏覽器斜做,那么你應該會喜歡上它,當我們在使用webview開發(fā)的時候缰揪,會發(fā)現(xiàn)webview存在許多的限制,并且開發(fā)者對webview不能完全控制,于是Chrome團隊為了解決開發(fā)者的這些問題钝腺,就設計出這個開源庫抛姑,只要用戶手機上安裝Chrome并且設置為默認瀏覽器,那么打開網(wǎng)頁鏈接的時候就會看到如下的畫面:

custom-tabs-client

是的艳狐!如此酷炫的畫面是用到了Chrome瀏覽器的內(nèi)核定硝,并且讀取Chrome的cookie,例如如果你在Chrome已經(jīng)登錄過github了毫目,那么通過這個庫打開的github鏈接同樣也顯示你已經(jīng)登錄了github蔬啡。當然除了頁面效果十分好之外,我們還可以自定義許多東西镀虐,例如過渡動畫箱蟆、ToolBar上方的ActionButton等等,我的項目中也已經(jīng)實現(xiàn)了這兩個功能刮便。接下來我?guī)Т蠹乙黄鹂纯醋詈唵蔚膶嵗龖撛趺淳帉懀?p>

CustomTabsIntent.Builder customTabsIntent;
 customTabsIntent = new CustomTabsIntent.Builder();     //獲取到CustomTabsIntent實例
 //一系列的設置
customTabsIntent.setToolbarColor(activity.getResources().getColor(R.color.colorPrimaryDark));   //設置ToolBar的顏色
customTabsIntent.setShowTitle(true);    //設置是否顯示網(wǎng)頁的標題
customTabsIntent.setStartAnimations(activity, R.anim.slide_in_right, R.anim.slide_out_left);    //設置進入的動畫
customTabsIntent.setExitAnimations(activity, R.anim.slide_in_left,R.anim.slide_out_right);      //設置退出的動畫
//開啟網(wǎng)頁
CustomTabActivityHelper.openCustomTab(
    activity,       //當前的activity
    customTabsIntent.build(),
    view,
    gank,   //gank帶有要打開的網(wǎng)頁的url
    new CustomFallback() { //如果用戶沒有安裝Chrome并將其設置為默認瀏覽器的話空猜,應該做這樣的處理
            @Override
            public void openUri(Activity activity, View view,Gank gank) {
                    Log.d("Gank", gank.toString());
                    super.openUri(activity, view,gank);
            }
    });

以上就是想要跟大家一起分享的關于這個項目中一些重要的點,可能有些地方講得并不那么清楚恨旱,但我覺得只有實踐才能出真知辈毯,所以老哥還是乖乖打開AS擼擼代碼啦!

版本控制

目前app的版本為V1.0.0搜贤,我會用下面的時間表記錄版本的迭代谆沃,如果有更新的版本,我會及時更新這個表格仪芒。

Version Date
V1.0.0 2017/5/14

致謝

作為一名Android開發(fā)者唁影,我們都應該具有像羅老師一樣感激開源世界的情懷,而我們現(xiàn)在能做的就是同樣為開源世界做貢獻桌硫,無論是寫文章亦或是寫程序夭咬,記得都要時刻保持一顆感恩的心。非常感謝代碼家以及他的干活集中營铆隘,也非常感謝許多前輩們做過的干活集中營app卓舵。

后記

最近一個月,感覺自己身體被掏空膀钠,吐槽學校對我們專業(yè)的課程安排如此不合理掏湾,每天上那些自己不感興趣的課程確實很無趣,但是生活再難也要感激它肿嘲,只有通過自己的雙手去努力融击,將來的你才會為現(xiàn)在的自己喝彩驕傲。下篇文章再見雳窟!

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尊浪,一起剝皮案震驚了整個濱河市匣屡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拇涤,老刑警劉巖捣作,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鹅士,居然都是意外死亡券躁,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門掉盅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來也拜,“玉大人,你說我怎么就攤上這事趾痘÷” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵扼脐,是天一觀的道長岸军。 經(jīng)常有香客問我,道長瓦侮,這世上最難降的妖魔是什么艰赞? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮肚吏,結果婚禮上方妖,老公的妹妹穿的比我還像新娘。我一直安慰自己罚攀,他們只是感情好党觅,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著斋泄,像睡著了一般杯瞻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上炫掐,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天魁莉,我揣著相機與錄音,去河邊找鬼募胃。 笑死旗唁,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的痹束。 我是一名探鬼主播检疫,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼祷嘶!你這毒婦竟也來了屎媳?” 一聲冷哼從身側響起夺溢,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎烛谊,沒想到半個月后企垦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡晒来,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了郑现。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片湃崩。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖接箫,靈堂內(nèi)的尸體忽然破棺而出攒读,到底是詐尸還是另有隱情,我是刑警寧澤辛友,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布薄扁,位于F島的核電站,受9級特大地震影響废累,放射性物質(zhì)發(fā)生泄漏邓梅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一邑滨、第九天 我趴在偏房一處隱蔽的房頂上張望日缨。 院中可真熱鬧旗吁,春花似錦渣淳、人聲如沸千扔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸳慈。三九已至檐涝,卻和暖如春酪捡,著一層夾襖步出監(jiān)牢的瞬間归榕,已是汗流浹背尸红。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蹲坷,地道東北人驶乾。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像循签,于是被迫代替她去往敵國和親级乐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,163評論 25 707
  • 個人原因县匠,此系列更新已停止风科,抱歉撒轮。 上一篇《看我開發(fā)干貨集中營App(二) ~ APP初始化》中講述了此APP所依...
    hucw閱讀 3,803評論 10 45
  • 西瓜子加清水用攪拌機打碎,小火煮兩個小時贼穆,加入冰糖题山,融合后起鍋,過濾出汁故痊。一次做多點放冰箱冷藏顶瞳,可以保存一周,每次...
    A太陽花閱讀 396評論 0 0
  • 談到理財,很多人首先想到的不是如何合理利用自己目前所擁有的資源戴甩,而是一味的抱怨自己目前收入太低而支出太高符喝。 其實在...
    青鳥的天空727閱讀 698評論 0 3
  • 九仙山是銅陵人熟悉的一座神靈之山。人們熟悉她的九仙石室甜孤、水操臺协饲、恩波寺、南少林和天地會遺址缴川,但她蘊藏著極其豐富茉稠、水...
    張哲民閱讀 295評論 4 8