我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情
作者:国民程序员
项目视频:https://www.bilibili.com/video/BV1vz4y1C7cC/
项目资料:微信搜索 【国民程序员】,回复 “github”
转载请保留此引用,感谢!
导语:
最近收到本书《Android App开发入门与实战》的一些读者的反馈,希望书籍最后章节的GitHub客户端实战开发环节能否单独拿出来讲解一遍,最好能通过视频形式展示出来。于是这段时间把GitHub客户端开发教程重新整理了一遍,并录制成视频。
这是第6篇,本篇正式进入编码阶段,首先介绍架构和模块的搭建。
本章节建议观看视频讲解。
微信搜索 【国民程序员】,回复 “github”,即可获取本项目源码和后续完整的实战文章教程。
一、架构
1. MVVM
BaseViewModel是业务VM的基类;
public abstract class BaseViewModel<T extends BaseRepository> extends AndroidViewModel {
protected Context context;
protected T repository;
public BaseViewModel(@NonNull Application application) {
super(application);
context = application;
repository = TUtil.getInstance(this, 0);
}
}
BaseRepository是业务Model的基类;
public abstract class BaseRepository {
private final String TAG = "BaseRepository";
protected MutableLiveData<Data<GithubAuth>> liveDataLogin;
public void login(String authorization) {
... ...
}
}
(附)AppRepository处理跟数据相关的业务入口;
二、模块
1. 网络
public enum RetrofitManager {
INSTANCE;
private final String TAG = "RetrofitManager";
private HashMap<String, Retrofit> retrofitMap = new HashMap<>();
private void createRetrofit(@NonNull String baseUrl, boolean isJson) {
int timeOut = Constant.HTTP_TIME_OUT;
Cache cache = new Cache(FileUtil.getHttpImageCacheDir(MyApplication.getInstance()),
Constant.HTTP_MAX_CACHE_SIZE);
// Log信息拦截器
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//这里可以选择拦截级别
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder()
.connectTimeout(timeOut, TimeUnit.MILLISECONDS)
.addInterceptor(loggingInterceptor)
.cache(cache);
if (!StringUtil.isEmpty(App.sAuthorization)) {
okHttpClientBuilder.interceptors().add(0, chain -> {
Request.Builder reqBuilder = chain.request()
.newBuilder().addHeader("Authorization", App.sLastLoginUser.getToken());
return chain.proceed(reqBuilder.build());
});
}
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())//定义转化器,用Gson将服务器返回的Json格式解析成实体
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//关联RxJava
.client(okHttpClientBuilder.build());
if (isJson) {
builder.addConverterFactory(GsonConverterFactory.create());
} else {
builder.addConverterFactory(SimpleXmlConverterFactory.createNonStrict());
}
retrofitMap.put(baseUrl + "-" + isJson, builder.build());
}
/**
* 区分登录态的Retrofit
*
* @param baseUrl
* @param withLogin
* @return
*/
public Retrofit getRetrofit(@NonNull String baseUrl, boolean withLogin) {
String key = baseUrl + "-" + withLogin;
if (!retrofitMap.containsKey(key)) {
createRetrofit(baseUrl, withLogin);
}
return retrofitMap.get(key);
}
public Retrofit getRetrofit(@NonNull String baseUrl) {
return getRetrofit(baseUrl, true);
}
}
2. 图片
QuickModule:自动切换功能模块的实现方式,以图片模块为例。
QuickModule.imageProcessor().loadNet(url, mImageView);
public class QuickModule {
private static IImageProcessor mIImageProcessor;
private static ImageConfig mImageConfig;
//配置生效
public static void launch() {
//image
if (mIImageProcessor == null) {
mIImageProcessor = new GlideProcessor();
}
mIImageProcessor.init(MyApplication.getInstance(), mImageConfig);
}
//image调用入口
public static <T extends IImageProcessor> T imageProcessor() {
if (mIImageProcessor != null) {
return (T) mIImageProcessor;
}
return (T) new GlideProcessor();
}
//image配置入口
public static ImageConfig configImage() {
return configImage(null);
}
//image配置入口
public static ImageConfig configImage(IImageProcessor processor) {
if (processor == null) {
mImageConfig = new ImageConfig();
}
else {
mIImageProcessor = processor;
mImageConfig = new ImageConfig();
}
return mImageConfig;
}
}
3. 数据库
Room主要由三部分组成:Database、Entity、Dao。
4. base
public abstract class BaseActivity extends QuickActivity {
//默认不使用自带titlebar
@Override
protected boolean isLoadDefaultTitleBar() {
return false;
}
@Override
protected void getBundleExtras(Bundle extras) {
}
//默认不开启eventbus
@Override
protected boolean isBindEventBus() {
return false;
}
@Override
protected void onEventComing(EventCenter eventCenter) {
}
@Override
protected Intent getGoIntent(Class<?> clazz) {
if (BaseFragment.class.isAssignableFrom(clazz)) {
Intent intent = new Intent(this, FragmentActivity.class);
intent.putExtra("fragmentName", clazz.getName());
return intent;
} else {
return super.getGoIntent(clazz);
}
}
}
public abstract class MVVMActivity<T extends BaseViewModel> extends BaseActivity {
protected T mViewModel;
public T getViewModel() {
return mViewModel;
}
public Class<T> getTClass() {
try {
return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void initViewsAndEvents(Bundle savedInstanceState) {
if (mViewModel == null) {
Class<T> clazz = getTClass();
if (clazz != null) {
mViewModel = ViewModelProviders.of(this).get(getTClass());
}
}
}
}
5. 数据
状态 + 泛型 + msg
public class Data<T> {
@Status
public int status;
@Nullable
public T data;
@Nullable
public String msg;
public Data(@Status int status, @Nullable T data, String msg) {
this.status = status;
this.data = data;
this.msg = msg;
}
public static <T> Data<T> loading() {
return new Data<>(Status.LOADING, null, null);
}
public static <T> Data<T> success(@Nullable T data) {
return new Data<>(Status.SUCCESS, data, null);
}
public static <T> Data<T> error(String msg) {
return new Data<>(Status.ERROR, null, msg);
}
public boolean showLoading() {
return status == Status.LOADING;
}
public boolean showSuccess() {
return status == Status.SUCCESS;
}
public boolean showError() {
return status == Status.ERROR;
}
}
6. 其它
- RxPermissions
RxPermissions rxPermissions = new RxPermissions(this);
rxPermissions
.request(Manifest.permission.CAMERA)
.subscribe(granted -> {
if (granted) {
ToastUtil.showToast("授权成功!");
} else {
ToastUtil.showToast("授权失败!");
}
});
- ButterKnife
private Unbinder mUnbinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
......
mUnbinder = ButterKnife.bind(this);
......
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mUnbinder != null) {
mUnbinder.unbind();
}
......
}
- EventBus
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
......
if (isBindEventBus()) {
EventBus.getDefault().register(this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (isBindEventBus()) {
EventBus.getDefault().unregister(this);
}
......
}
感兴趣的朋友可以查看下一篇博客:[s1e7]超详细!3小时从0开始开发一个GitHub客户端
想要获取本实战项目后续完整文章教程和视频内容,请在微信搜索 【国民程序员】,回复 “github”即可。
欢迎关注我的技术公众号:国民程序员,我们的目标:输出干货
- 每天分享原创技术文章
- 海量免费技术资料和视频学习资源
- 分享赚钱门道,带领程序员走向财务自由
