歡迎訪問我的個人博客训唱,原文鏈接:http://wensibo.top/2017/05/15/GankClient/ 玫霎,未經(jīng)允許不得轉發(fā)凿滤!
前言
今天想要與大家一起分享的是近一個星期內(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)寒冬)
好啦恍箭,上面講了一大堆廢話終于可以進入正題了刻恭,我也很基動,開車咯扯夭!
項目介紹
GankClient(又稱干貨集中營客戶端)是一個全新的干貨集中營客戶端吠各,它獲取的是來自干貨集中營API的數(shù)據(jù)臀突,利用全新的Material Design的設計語言展示數(shù)據(jù)內(nèi)容。整個項目采用MVP的設計架構贾漏,并且大量使用RxJava2候学,網(wǎng)絡框架使用的是Retrofit。我用下面幾個裝逼的句子來形容一下這個APP:
- 更快速的加載速度
- 更流暢的頁面體驗
- 更有趣的刷新效果
- 更精美的網(wǎng)頁瀏覽
- 更美觀的視覺享受
這個只是我的個人感受纵散,大神請輕噴:joy: 梳码,不過還是希望大家能夠喜歡這個項目,并且積極的向我pull request以及反饋bug伍掀,希望大家多多支持掰茶。如果可以的話給個star咯。
預覽
全部效果圖來一發(fā)
沒有gif圖都不好意思說話了
![gif](http://wensibo.top/file/img/2017-5-15GankClient/gank.gif)
下載
如果你想測試這個項目蜜笤,那么請手動clone濒蒋,如果你想嘗試一下APP,那么你可以使勁戳這里 ,或者掃下面的二維碼把兔。后期我會發(fā)布到應用市場沪伙,希望大家可以多多支持!
功能&特色
加醋的表示已經(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
- model
- 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)頁鏈接的時候就會看到如下的畫面:
是的艳狐!如此酷炫的畫面是用到了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)在的自己喝彩驕傲。下篇文章再見雳窟!