Github
项目的起因
Github上一个看起来很漂亮的Github客户端
成功引起了我的注意
但是,它不开源
作者在贴了一堆截图后留下了自己的商务合作邮箱
我不开心所以也想做一个
本文的目的
- 如果你是青铜玩家:希望本文提供的一些资料(如API,架构,三方,功能实现思路等)可以给你一些参考价值
- 如果你是王者玩家:欢迎指出问题和建议,尤其是优化和架构方面
架构和三方
基于 google-android-architecture-mvp-rxjava 的RxJava + Retrofit + Mvp架构,该架构会在后面详细讲解,三方库如下
Rx
快速开发工具
- butterknife 大名鼎鼎的黄油刀,让你不再findById
- android_dbinspector 不需要root就可以查看真机上数据库内容
- fastjson 最快的json解析工具,阿里巴巴出品
网络相关
- Retrofit 新一代网络请求神器
- OkHttp logging interceptor 请求日志拦截器
图片加载
- Glide 图片加载框架
UI
- MaterialSearchView Material Design风格的搜索
- CircleImageview 圆形头像
- BaseRecyclerViewAdapterHelper 强大的RecyclerView万能适配器
- FloatingActionButton Material Design风格的浮动按钮
- spots-dialog 闪烁的loding进度条
- materialish-progress 旋转的菊花圈
- MarkdownView 将markdown格式的字符串显示成漂亮的html页面
- WaitingDots 闪烁的loding动画
- CodeView 将代码显示成漂亮的样式
- material-dialogs Material风格的Dialog
功能介绍
Explore
- 浏览Repository和User,使用选项卡切换,并且将浏览过的数据缓存在本地(本应用所有数据都做了缓存,并且缓存时间可由用户定制)
- 支持关键字搜索Repository和User,可以选择排序方式(Most star,Best match,Most fork,Rencent update等),可以按标签换语言分类(排序方式和标签可用用户定制)
RepositoryDetail
- Repository简要信息查看,并且可以进行star,unstar,fork操作
- 异步加载ReadMe,按markdown格式显示ReadMe
- 显示code树,查看代码内容,因为缓存的原因,点击加载过的节点可以秒加载
UserDetail
- User简要信息查看,并且可以进行follow,unfollow操作
RepositoryList
- 查询自己的Repository
- 查询自己Star过的Repository
- 查询RepositoryDetail被fork过的Repository
- 查询UserDetail被拥有的Repository
UserList
- 查询自己,以及其他User的following和follower
- 查询RepositoryDetail的Contributors和Stargazers
Event
- 可以查询,自己,User,Repository的Event
Setting
- 设置Explore页面首先查询的语言,右下方应该有几个语言选项,默认的排序方式
架构分析
MVP
谷歌去年在github上发布一整套的它推荐的Android架构Demo,todo-mvp-rxjava 是之中用来示范rxjava的sample
关于它的这套架构,我画了一个栩栩如生的草图,嗯,栩栩如生
是不是已经被我的美术功底震惊的说不出话来,就冲这图你不给Star一个?
RxJava
上一节中有两个地方是十足的伪代码,mPresenter.loadList和Repository的具体实现,使用RxJava可以很容易的完成这两个部分的实现
对RxJava还没有概念的请看 给Android 开发者的 RxJava 详解
这里直接展示用法
添加依赖
compile 'io.reactivex:rxjava:1.0.8'
compile 'io.reactivex:rxandroid:1.2.1'
- 使用RxJava将两个数据源的结果合并返回,返回类型改成了Observable,使用了concat操作符来合并两个数据源,使用first操作符来返回第一个结果
public interface DataSource {
Observable loadList();
}
public class LocalDataSource implements DataSource {
@Override
public Observable loadList() {
return Observable.create(new Observable.OnSubscribe<List>() {
@Override
public void call(Subscriber<? super List> subscriber) {
List list = new ArrayList();//从本地读取的缓存
subscriber.onNext(list);
}
});//从本地读取缓存
}
}
public class RemoteDataSource implements DataSource{
@Override
public Observable loadList() {
return null;//从网络加载数据
}
}
public class Repository implements DataSource{
private DataSource mRemoteDataSource;
private DataSource mLocalDataSource;
public Repository(DataSource remoteDataSource,DataSource lemoteDataSource){
mRemoteDataSource = remoteDataSource;
mLocalDataSource = lemoteDataSource;
}
@Override
public Observable loadList() {
Observable localTask = mLocalDataSource.loadList();
Observable remoteTask = mRemoteDataSource.loadList();
return Observable.concat(localTask, remoteTask).first();//让本地缓存先读取,网络拉去后执行,谁先拿到数据就返回谁
}
}
- 使用RxJava实现mPresenter.loadList中的跳转逻辑,避免了使用八百个回调来切换线程
public class PrensenterImpl implements Contract.Presenter {
...
@Override
public void loadList() {
//UI 线程
mView.showLoading();
mRepository.loadList()
.subscribeOn(Schedulers.io()) //指定上游在IO线程执行
.observeOn(AndroidSchedulers.mainThread()) //指定下游在UI线程
.subscribe(new Observer<List>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
mView.hideLoading();
mView.showError();
}
@Override
public void onNext(List list) {
mView.hideLoading();
if (list.isEmpty()) {
mView.showEmpty();
} else {
mView.showList(list);
}
}
});
}
}
网友评论