欢迎掘金的小伙伴们访问个人博客网站,原文连接: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。
最近一个月,感受本身身体被掏空,吐槽学校对咱们专业的课程安排如此不合理,天天上那些本身不感兴趣的课程确实很无趣,可是生活再难也要感激它,只有经过本身的双手去努力,未来的你才会为如今的本身喝彩骄傲。下篇文章再见!