歡迎掘金的小夥伴們訪問個人博客網站,原文連接:wensibo.top/2017/05/15/… ,未經容許不得轉載!java
今天想要與你們一塊兒分享的五月份的時候用一個星期開發的一個app——乾貨集中營客戶端,由於已經得到了掘金的專欄因此就把以前的文章發不上來與你們一塊兒分享。
其實網上已經有許多相似的項目,代碼家也在他的乾貨集中營中推薦了幾款優秀的做品,我也借鑑了其中的一些,本身開發出一款乾貨集中營客戶端,目前項目已經發布到github,若是你想了解整個工程的具體內容,那麼你能夠fork或者clone,若是你以爲我作得還能夠,那麼請你賜給我一個star唄!你的支持會是我努力的動力。android
慢慢的已經養成了每篇文章都會來一個前言,也慢慢地將寫文章潛移默化的轉變成寫故事,因此每一個故事都會有前言,也都會有結果,此次也不例外。
距離上篇引發熱烈反響的文章發佈已通過去一個月了,承蒙廣大網友對個人支持以及建議,固然做爲一個90後,我也很虛心的接受來自各方的吐槽,畢竟我並不優秀,只是一直在優秀的路上努力的奔跑着。下面我想跟你們一塊兒分享一下這一個月裏我作了些什麼事,以及接下來一段時間的計劃和打算。git
這個只是個人我的感覺,大神請輕噴:joy: ,不過仍是但願你們可以喜歡這個項目,而且積極的向我pull request以及反饋bug,但願你們多多支持。若是能夠的話給個star咯。 github
若是你使用酷安的話,那就使勁點這裏,或者在酷安搜索乾貨集中營
,認準個人圖標哦
web
若是你沒有安裝酷安,那麼你能夠掃描下方的二維碼進行下載
chrome
若是你想測試這個項目,那麼請手動clone數據庫
√表示已經實現的功能,X表示的的是還沒實現或者須要完善的功能。(吐槽一下,掘金的MarkDown編輯器仍是沒有實現一些基本的語法,例如打勾勾) 編程
√實時獲取服務器的最新數據,採用CardView的佈局以更好的展示數據。
√刷新效果很好玩,真的很精緻,感謝Phoenix。
√若是你裝有Chrome瀏覽器,並將其設置爲默認瀏覽器,那麼你的網頁瀏覽效果就會十分酷炫。感謝Custom-Tabs-Client ! 牆裂推薦Chrome,若是你沒有安裝Chrome,那也不要緊,那就用傳統的WebView吧!
√更加統一的過渡動畫,相信你會愛上它。
√保存、分享圖片與連接,也能夠直接使用瀏覽器打開連接。
√更好看的Material Design設計風格。
√妹子很漂亮喲! api
X優化webview的視頻播放。
X增長使用系統瀏覽器的選項。
X修復在主界面中加載數據到2016/4/20左右時數據顯示錯亂的問題。
X加強分享功能。 瀏覽器
終於到了這個純乾貨步驟了,別說話先看東西!
我先展現如下這個項目的結構圖,讓你們內心有個底
能夠看到,整個項目的結構還算比較清晰,總體的架構都是在mvp目錄中定下來的,mvp架構分三層,model模型層,用於定義一些數據的類型;presenter呈現者層,用於處理view層的邏輯;view顯示層,這裏定義的都是接口,真正實現他們的是activity,這些activity只要實現相應的接口,就可以本身複寫其中的方法。
固然我這麼說你確定仍是一臉懵逼,並且我還必須跟你說,我這個不算最純粹的MVP模式,最純粹的寫法應該都是面向接口編程的,就是在model,presenter,以及view下都是定義接口,而到了具體的運用場景,就定義出具體的類去實現這些接口。固然了,爲了讓你們可以更清楚MVP是怎麼實現的,下面我會用代碼的形式爲你們展現,例如我要編寫MainActivity的代碼,首先已經知道在這個Activity中須要作以下這些事:
爲了讓Activity專一於界面的工做,而不用去考慮邏輯處理的操做,這個就是所謂的解耦,那麼咱們能夠將邏輯的操做放到presenter中去,而與界面有關的操做就放在view下,因而咱們就能夠這樣寫(爲了便於你們理解,我將項目中的代碼作了適當的修改,若是你想了解更加具體的邏輯,能夠仔細看看代碼):
public interface IBaseView {
//界面初始化操做
void init();
}複製代碼
/** * 將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);
}複製代碼
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();
}
}複製代碼
大概就是這樣一個套路,講真我這樣講你確定迷糊,我當初在學這個的時候也是十分凌亂,後來才發現只有本身動手親自敲代碼才能瞭解整個思路,另外你們在學習MVP的過程當中應該擅於畫圖,無論是在紙上畫仍是使用思惟導圖都行,這樣可讓你更加宏觀的瞭解整個調用的順序以及各個類之間的關係,這毫不是你看了一篇文章就能懂的。
當我問這個問題的時候,其實我想說的是RxJava的用處很廣,咱們想固然的認爲只要RxJava與Retrofit相配合就算是完成任務了,但實際上只要涉及到耗時操做、線程切換:網絡請求、圖片解析、數據庫讀取等等須要用多個線程一塊兒完成的工做時,你均可以用到RxJava,而且若是你還一直用RxJava1的話,那麼你也OUT啦,當你認識RxJava2.x的時候你會發現他更強大了。關於RxJava,我後續會寫相關的文章與你們一塊兒分享,這裏我舉項目中遇到的一個例子,看看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();
}
}複製代碼
還記得以前我寫過Volley的一系列文章,雖然以爲這個開源框架已經不錯了,但畢竟長江後浪推前浪,在Retrofit的面前,Volley簡直就是小巫見大巫,看看咱們應該如何在項目中使用:
public interface GankRetrofit {
//獲取MainActivity界面的數據,具體的請求路徑應該詳細看官方的API說明,
// Retrofit與RxJava配合以後才能顯示出更強的威力
@GET("data/{type}/40/{page}")
Observable<MainData> getMainData(@Path("type") String type, @Path("page") int page);
}複製代碼
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的對象複製代碼
//返回的Observable<MainData>對象就可使用RxJava進行解析了
gankRetrofit.getMainData("Android",40);複製代碼
若是你使用過Chrome瀏覽器,那麼你應該會喜歡上它,當咱們在使用webview開發的時候,會發現webview存在許多的限制,而且開發者對webview不能徹底控制,因而Chrome團隊爲了解決開發者的這些問題,就設計出這個開源庫,只要用戶手機上安裝Chrome而且設置爲默認瀏覽器,那麼打開網頁連接的時候就會看到以下的畫面:
CustomTabsIntent.Builder customTabsIntent;
customTabsIntent = new CustomTabsIntent.Builder(); //獲取到CustomTabsIntent實例
//一系列的設置
customTabsIntent.setToolbarColor(activity.getResources().getColor(R.color.colorPrimaryDark)); //設置ToolBar的顏色
customTabsIntent.setShowTitle(true); //設置是否顯示網頁的標題
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); //設置退出的動畫
//開啓網頁
CustomTabActivityHelper.openCustomTab(
activity, //當前的activity
customTabsIntent.build(),
view,
gank, //gank帶有要打開的網頁的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開發者,咱們都應該具備像羅老師同樣感激開源世界的情懷,而咱們如今能作的就是一樣爲開源世界作貢獻,不管是寫文章亦或是寫程序,記得都要時刻保持一顆感恩的心。很是感謝代碼家以及他的幹活集中營,也很是感謝許多前輩們作過的幹活集中營app。
最近一個月,感受本身身體被掏空,吐槽學校對咱們專業的課程安排如此不合理,天天上那些本身不感興趣的課程確實很無趣,可是生活再難也要感激它,只有經過本身的雙手去努力,未來的你纔會爲如今的本身喝彩驕傲。下篇文章再見!