为了开发效率,记录一下自己的开发框架,整体使用mvvm的模式,使用android自带的databinding开发数据驱动的页面逻辑。
大致分为几个部分,common存放一般在各个模块都会用到的类,module是项目模块,主要是业务模块,如user用户模块,user下有有三个包ui/model/viewCtrl ui存放该模块下的Activity,viewCtrl存放的是业务处理逻辑类,用过databinding的都知道,databing可以绑定类,viewCtrl就是界面视图的逻辑类,model存放数据模型。network是网路框架,utils是工具包,views是自定义的view
github地址:temp模板地址
项目适配的方案是以限定符进行适配,以screeMatch工具批量生成。参考
项目中所用到三方库:
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.zjhc.jxzq.temp"
minSdkVersion 15
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
}
dataBinding {
enabled = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildTypes {
release {
//是否开启zip优化
zipAlignEnabled true
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
applicationVariants.all { variant ->
variant.outputs.all { output->
def outputFile = output.outputFile
def fileName
if(outputFile != null && outputFile.name.endsWith('.apk')){
if(variant.buildType.name.equals('release')){
fileName = "App${defaultConfig.versionName}.apk"
}else if(variant.buildType.name.equals('debug')){
fileName = "App${defaultConfig.versionName}_debug.apk"
}
outputFileName = fileName
}
}
}
}
}
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
compile 'com.android.support:design:27.1.1'
//ARouter
annotationProcessor 'com.alibaba:arouter-compiler:1.1.2'
compile 'com.alibaba:arouter-api:1.2.1'
//底部导航栏
implementation 'com.ashokvarma.android:bottom-navigation-bar:2.0.3'
//沉浸式布局
compile 'com.readystatesoftware.systembartint:systembartint:1.0.3'
//retrofit+rxjava
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
compile 'io.reactivex.rxjava2:rxjava:2.1.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
//gson
compile 'com.google.code.gson:gson:2.8.0'
//mvvm的recycleview的封装
compile 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:2.1.0'
compile 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:2.1.0'
//强大的 RecyclerView 适配器
compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.22'
//glide
implementation 'com.github.bumptech.glide:glide:3.5.2'
//SwipeToLoadLayout 下拉刷新控件
compile 'com.github.Aspsine:SwipeToLoadLayout:1.0.4'
}
项目中使用ARouter框架进行页面跳转,注意,ARouter的路径必须两级以上。
框架中的重点是对于网络和列表加载的封装,网路参考这篇参考
//列表使用方法
<data>
<import type="me.tatarka.bindingcollectionadapter2.LayoutManagers" />
<variable
name="viewCtrl"
type="com.zjhc.jxzq.jxzq.module.home.viewCtrl.SearchCompanyCtrl" />
</data>
<com.aspsine.swipetoloadlayout.SwipeToLoadLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:listener="@{viewCtrl.listener}">
<android.support.v7.widget.RecyclerView
android:id="@+id/swipe_target"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:addItemDecoration="@{viewCtrl.viewModel.type}"
app:itemBinding="@{viewCtrl.viewModel.onItemBind}"
app:items="@{viewCtrl.viewModel.items}"
app:layoutManager="@{LayoutManagers.linear()}" />
</com.aspsine.swipetoloadlayout.SwipeToLoadLayout>
在框架中大量使用了自定义属性BindingAdapter,app:listener实现了下拉刷新,上拉加载的方式, app:addItemDecoration实现了列表的分隔符,app:itemBinding绑定item布局, app:items绑定数据源, app:layoutManager实现列表布局方式。参考
项目中对于应用生命周期的管理在MyApplication中实现:
this.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
addActivity(activity);
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
if(mActivity == null){
mActivity = activity;
}else{
if(mActivity != activity){
mActivity = activity;
}
}
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
removeActivity(activity);
}
});
//添加actiivty
public void addActivity(Activity actiivty){
if(!activityList.contains(actiivty)){
activityList.add(actiivty);
}
}
//销毁单个Activity
public void removeActivity(Activity activity){
if(activityList.contains(activity)){
activityList.remove(activity);
}
}
//销毁所有的activity
public static void removeAllActivity(){
for(Activity activity :activityList){
activity.finish();
}
}
以lifecycle管理生命周期,在Activity创建时添加,如果需要每次打开手势验证,可以对存储的activity进行进行判断,是否加载手势页。注意,使用dialog的时候请勿使用application中存储的activity,因为页面的不可见会导致dialog创建失败。
为了项目的性能与调试,统一管理项目的常量属性存储于BaseParm和Constant中。为了后期维护,主要勤写注释,类的使用需要注明类的用途,单层调用可以写上{@link 调用它的类} 以link链接到调用此类的方法便于调试。
/**
* @Author 作者
* @Date 2018/7/6.
* @Description 类的作用
* {@link 类名 }
*/