项目的整体框架使用:MVP+Dagger2+RXJava2+Retrofit+RxBus+ RXBinding+RxLifecyle+Java1.8的Lambda
1、人脸识别
2、生成PDF文件
3、微信,QQ登陸
4、扫描二维码
5、自定义数字键盘
6、搜索按钮
7、头像上传
8、区域选择
9、IP获取,区域选择,定位功能
PDF数字签名
MVP的使用:
Dagger2的使用:
RXJava的使用:
使得AndroidStudio支持Java8的Lambda特性:
Android注解使用之注解编译android-apt如何切换到annotationProcessor
Retrofit的使用:
白天模式和夜间模式
当前代码在Application的onCreate方法中调用AppCompatDelegate.setDefaultNightMode来初始化夜间模式
if (dataManager.getNightModeState()) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
在SettingActivity设置页面点击白天黑夜模式切换:
@Override
public void useNightMode(boolean isNight) {
if (isNight == mPresenter.getNightModeState()) {
return;
}
mPresenter.setNightModeState(isNight);
if (isNight) {
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_NO);
}
recreate();
}
数据加载的进度条以及数据加载失败的提示内容
项目中的Activity,耗时操作需要加载进度条,以及获取数据成功或者失败的情况页面替换
需要继承自RootActivity,加载数据的过程需要调用showLoading(),
数据加载成功时候调用showMain(),加载失败的时候需要调用showError();
需要当前页面的主要数据有一个控件的ID是view_main;
/**
* @author: AFinalStone 602392033@qq.com
* @date: 2017/4/21
* @desciption:
*/
public abstract class RootActivity<T extends BaseContract.BasePresenter> extends BaseActivity<T>{
private static final int STATE_MAIN = 0x00;
private static final int STATE_LOADING = 0x01;
private static final int STATE_ERROR = 0x02;
private ProgressImageView ivLoading;
private View viewError;
private View viewLoading;
private ViewGroup viewMain;
private ViewGroup mParent;
private int mErrorResource = R.layout.view_error;
private int currentState = STATE_MAIN;
private boolean isErrorViewAdded = false;
@Override
protected void initEventAndData() {
viewMain = (ViewGroup) findViewById(R.id.view_main);
if (viewMain == null) {
throw new IllegalStateException(
"The subclass of RootActivity must contain a View named 'view_main'.");
}
if (!(viewMain.getParent() instanceof ViewGroup)) {
throw new IllegalStateException(
"view_main's ParentView should be a ViewGroup.");
}
mParent = (ViewGroup) viewMain.getParent();
View.inflate(mContext, R.layout.view_progress, mParent);
viewLoading = mParent.findViewById(R.id.view_loading);
ivLoading = (ProgressImageView) viewLoading.findViewById(R.id.iv_progress);
viewLoading.setVisibility(View.GONE);
viewMain.setVisibility(View.VISIBLE);
}
@Override
public void showError() {
if (currentState == STATE_ERROR)
return;
if (!isErrorViewAdded) {
isErrorViewAdded = true;
View.inflate(mContext, mErrorResource, mParent);
viewError = mParent.findViewById(R.id.view_error);
if (viewError == null) {
throw new IllegalStateException(
"A View should be named 'view_error' in ErrorLayoutResource.");
}
}
hideCurrentView();
currentState = STATE_ERROR;
viewError.setVisibility(View.VISIBLE);
}
@Override
public void showLoading() {
if (currentState == STATE_LOADING)
return;
hideCurrentView();
currentState = STATE_LOADING;
viewLoading.setVisibility(View.VISIBLE);
ivLoading.start();
}
@Override
public void showMain() {
if (currentState == STATE_MAIN)
return;
hideCurrentView();
currentState = STATE_MAIN;
viewMain.setVisibility(View.VISIBLE);
}
private void hideCurrentView() {
switch (currentState) {
case STATE_MAIN:
viewMain.setVisibility(View.GONE);
break;
case STATE_LOADING:
ivLoading.stop();
viewLoading.setVisibility(View.GONE);
break;
case STATE_ERROR:
if (viewError != null) {
viewError.setVisibility(View.GONE);
}
break;
}
}
public void setErrorResource(int errorLayoutResource) {
this.mErrorResource = errorLayoutResource;
}
}
RXBinding的使用
RxBus的使用
RxLifecyle的使用
RxJava2+Retrofit2+RxLifecycle2使用MVP模式构建项目
Android 使用RxLifecycle解决RxJava内存泄漏
RxPermission的使用
使用RxPermission框架对android6.0权限进行检测
测试
Android自动化测试工具 UiAutomator使用详解
二维码扫描
QRCode 扫描二维码、扫描条形码、相册获取图片后识别、生成带 Logo 二维码、支持微博微信 QQ 二维码扫描样式
数据库
8.5.1版本的bufferKnife对Java1.8的支持有问题