Skip to content

Commit

Permalink
Merge branch '1.2.10'
Browse files Browse the repository at this point in the history
# Conflicts:
#	app/build.gradle
#	app/src/main/java/xyz/mxlei/app/app/AppApplication.java
#	app/src/main/java/xyz/mxlei/app/data/source/http/HttpDataSource.java
#	app/src/main/java/xyz/mxlei/app/ui/MainActivity.java
#	app/src/main/java/xyz/mxlei/app/ui/MainViewModel.java
#	app/src/main/res/layout/activity_main.xml
#	build.gradle
#	config.gradle
#	gradle/wrapper/gradle-wrapper.properties
#	mvvmx/build.gradle
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/base/BaseActivity.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/base/BaseApplication.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/base/BaseFragment.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/base/BaseLazyActivity.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/base/BaseLazyFragment.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/base/BaseViewModel.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/base/ContainerActivity.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/base/ViewModelFactory.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/bus/RxBus.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/bus/RxSubscriptions.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/http/BaseResponse.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/http/interceptor/CacheInterceptor.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/http/interceptor/HeaderInterceptor.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/utils/ImageUtils.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/utils/RxUtils.java
#	mvvmx/src/main/java/xyz/mxlei/mvvmx/utils/compression/Luban.java
#	nexus.gradle
  • Loading branch information
jeffery committed Sep 4, 2023
2 parents b6fc396 + abdfe2d commit fea54cf
Show file tree
Hide file tree
Showing 43 changed files with 2,057 additions and 2,279 deletions.
64 changes: 8 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,16 @@
# Android-MVVM-Framework
1. DataBinding+LiveData+ViewModel框架为基础
2. 整合Okhttp+RxJava+Retrofit+Glide等流行模块
3. 各种原生控件自定义的BindingAdapter,让事件与数据源完美绑定的一款容易上瘾的实用性MVVM快速开发框架。从此告别findViewById(),告别setText(),告别setOnClickListener()

## 框架特点
- **快速开发**

只需要写项目的业务逻辑,不用再去关心网络请求、权限申请、View的生命周期等问题,撸起袖子就是干
只需要写项目的业务逻辑,不用再去关心网络请求、权限申请、View的生命周期等问题。

- **维护方便**

MVVM开发模式,低耦合,逻辑分明。Model层负责将请求的数据交给ViewModel;ViewModel层负责将请求到的数据做业务逻辑处理,最后交给View层去展示,与View一一对应;View层只负责界面绘制刷新,不处理业务逻辑,非常适合分配独立模块开发。

- **流行框架**

[retrofit](https://github.com/square/retrofit)+[okhttp](https://github.com/square/okhttp)+[rxJava](https://github.com/ReactiveX/RxJava)负责网络请求;[gson](https://github.com/google/gson)负责解析json数据;[glide](https://github.com/bumptech/glide)负责加载图片;[rxlifecycle](https://github.com/trello/RxLifecycle)负责管理view的生命周期;与网络请求共存亡;[rxbinding](https://github.com/JakeWharton/RxBinding)结合databinding扩展UI事件;[rxpermissions](https://github.com/tbruyelle/RxPermissions)负责Android 6.0权限申请;[material-dialogs](https://github.com/afollestad/material-dialogs)一个漂亮的、流畅的、可定制的material design风格的对话框。

- **数据绑定**

满足google目前控件支持的databinding双向绑定,并扩展原控件一些不支持的数据绑定。例如将图片的url路径绑定到ImageView控件中,在BindingAdapter方法里面则使用Glide加载图片;View的OnClick事件在BindingAdapter中方法使用RxView防重复点击,再把事件回调到ViewModel层,实现xml与ViewModel之间数据和事件的绑定(框架里面部分扩展控件和回调命令使用的是@kelin原创的)。

- **基类封装**

专门针对MVVM模式打造的BaseActivity、BaseFragment、BaseViewModel,在View层中不再需要定义ViewDataBinding和ViewModel,直接在BaseActivity、BaseFragment上限定泛型即可使用。普通界面只需要编写Fragment,然后使用ContainerActivity盛装(代理),这样就不需要每个界面都在AndroidManifest中注册一遍。

- **全局操作**
1. 全局的Activity堆栈式管理,在程序任何地方可以打开、结束指定的Activity,一键退出应用程序。
2. LoggingInterceptor全局拦截网络请求日志,打印Request和Response,格式化json、xml数据显示,方便与后台调试接口。
3. 全局Cookie,支持SharedPreferences和内存两种管理模式。
4. 通用的网络请求异常监听,根据不同的状态码或异常设置相应的message。
5. 全局的异常捕获,程序发生异常时不会崩溃,可跳入异常界面重启应用。
6. 全局事件回调,提供RxBus、Messenger两种回调方式。
7. 全局任意位置一行代码实现文件下载进度监听(暂不支持多文件进度监听)。
8. 全局点击事件防抖动处理,防止点击过快。


## 1、准备工作
> 网上的很多有关MVVM的资料,在此就不再阐述什么是MVVM了,不清楚的朋友可以先去了解一下。[todo-mvvm-live](https://github.com/googlesamples/android-architecture/tree/todo-mvvm-live)
Expand All @@ -48,38 +25,29 @@ dataBinding {
从远程依赖:

在根目录的build.gradle中加入

```gradle
allprojects {
repositories {
...
google()
jcenter()
maven { url 'https://jitpack.io' }
//佳博打印SDK仓库
maven("http://118.31.6.84:8081/repository/maven-public/") {
isAllowInsecureProtocol = true
}
}
}
```
在主项目app的build.gradle中依赖
```gradle
dependencies {
...
implementation 'xyz.xmlei:mvvmx:1.2.5'
implementation 'com.gainscha:mvvmx:2.0.2-SNAPSHOT'
}
```
### 1.3、配置config.gradle
如果不是远程依赖,而是下载的例子程序,那么还需要将例子程序中的config.gradle放入你的主项目根目录中,然后在根目录build.gradle的第一行加入:

```gradle
apply from: "config.gradle"
```

**注意:** config.gradle中的

android = [] 是你的开发相关版本配置,可自行修改

support = [] 是你的support相关配置,可自行修改

dependencies = [] 是依赖第三方库的配置,可以加新库,但不要去修改原有第三方库的版本号,不然可能会编译不过
### 1.4、配置AndroidManifest
### 1.3、配置AndroidManifest
添加权限:
```xml
<uses-permission android:name="android.permission.INTERNET" />
Expand Down Expand Up @@ -689,19 +657,3 @@ ImageUtils.compressWithRx(filePaths, new Subscriber() {
}
});
```
### 3.6、其他辅助类
**ToastUtils:** 吐司工具类

**MaterialDialogUtils:** Material风格对话框工具类

**SPUtils:** SharedPreferences工具类

**SDCardUtils:** SD卡相关工具类

**ConvertUtils:** 转换相关工具类

**StringUtils:** 字符串相关工具类

**RegexUtils:** 正则相关工具类

**KLog:** 日志打印,含json格式打印
29 changes: 17 additions & 12 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
apply plugin: 'com.android.application'

android {
compileSdkVersion 30
compileSdk = 33
defaultConfig {
applicationId 'xyz.mxlei.mvvmx'
minSdkVersion 22
targetSdkVersion 30
minSdk = 30
targetSdk = 30
versionCode 1
versionName '1.0'
versionName "1.0"
multiDexEnabled true
}
buildTypes {
release {
Expand All @@ -19,24 +20,28 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
buildFeatures{
buildFeatures {
dataBinding true
}
}

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation androidx.material
implementation androidx.cardview
implementation androidx.appcompat
implementation androidx.constraintlayout
implementation androidx.multidex
implementation depends.retrofit
implementation depends.retrofit_converter_gson
implementation depends.retrofit_adapter_rxjava
debugImplementation depends.leakcanary
debugImplementation depends.leakcanary_fragment
//下拉刷新,上拉加载
implementation depends.smart_refresh_core
implementation depends.smart_refresh_header_classics
implementation depends.smart_refresh_footer_classics

implementation 'com.lcodecorex:tkrefreshlayout:1.0.7'
//底部tabBar
implementation('me.majiajie:pager-bottom-tab-strip:2.2.5') {
exclude group: 'com.android.support'
}
// implementation mxlei.mvvmx
implementation project(':mvvmx')

debugImplementation depends.leakcanary
}
47 changes: 29 additions & 18 deletions app/src/main/java/xyz/mxlei/app/app/AppApplication.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,42 @@
package xyz.mxlei.app.app;

import android.content.Context;
import android.os.Build;
import android.app.Application;

import androidx.multidex.MultiDex;
import com.squareup.leakcanary.LeakCanary;

import xyz.mxlei.mvvmx.base.BaseApplication;
import xyz.mxlei.app.BuildConfig;
import xyz.mxlei.app.R;
import xyz.mxlei.app.ui.MainActivity;
import xyz.mxlei.mvvmx.crash.CaocConfig;
import xyz.mxlei.mvvmx.utils.KLog;

/**
* @author mxlei
*/
public class AppApplication extends BaseApplication {

@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
//安卓5.0以下需要处理多DEX,5.0及以上不需要
MultiDex.install(this);
}
}
public class AppApplication extends Application {

@Override
public void onCreate() {
super.onCreate();
//是否开启打印日志
KLog.init(true);
KLog.init(BuildConfig.DEBUG);
//初始化全局异常崩溃
initCrash();
//内存泄漏检测
if (!LeakCanary.isInAnalyzerProcess(this)) {
LeakCanary.install(this);
}
}

private void initCrash() {
CaocConfig.Builder.create()
.backgroundMode(CaocConfig.BACKGROUND_MODE_SILENT) //背景模式,开启沉浸式
.enabled(true) //是否启动全局异常捕获
.showErrorDetails(true) //是否显示错误详细信息
.showRestartButton(true) //是否显示重启按钮
.trackActivities(true) //是否跟踪Activity
.minTimeBetweenCrashesMs(2000) //崩溃的间隔时间(毫秒)
.errorDrawable(R.mipmap.ic_launcher) //错误图标
.restartActivity(MainActivity.class) //重新启动后的activity
// .errorActivity(YourCustomErrorActivity.class) //崩溃后的错误activity
// .eventListener(new YourCustomEventListener()) //崩溃后的错误监听
.apply();
}
}
Original file line number Diff line number Diff line change
@@ -1,50 +1,37 @@
package xyz.mxlei.app.data.source.http;

import android.content.Context;

import java.util.concurrent.TimeUnit;

import io.reactivex.rxjava3.core.Observable;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import xyz.mxlei.app.data.source.http.service.ApiService;
import xyz.mxlei.mvvmx.http.cookie.CookieJarImpl;
import xyz.mxlei.mvvmx.http.cookie.store.PersistentCookieStore;

/**
* 网络数据源
*
* @author mxlei
* @date 2019/03/07
*/
public class HttpDataSource implements ApiService {
private final ApiService apiService;
private final OkHttpClient okhttpClient;
private volatile static HttpDataSource INSTANCE = null;
private static final String BASE_URL = "http://mxlei.xyz/";

private HttpDataSource(Context context) {
okhttpClient = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
.cookieJar(new CookieJarImpl(new PersistentCookieStore(context.getApplicationContext())))
.build();
private HttpDataSource() {
apiService = new Retrofit.Builder()
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(okhttpClient)
.baseUrl(BASE_URL)
.build()
.create(ApiService.class);
}

public static HttpDataSource getInstance(Context context) {
public static HttpDataSource getInstance() {
if (INSTANCE == null) {
synchronized (HttpDataSource.class) {
if (INSTANCE == null) {
INSTANCE = new HttpDataSource(context);
INSTANCE = new HttpDataSource();
}
}
}
Expand Down
25 changes: 5 additions & 20 deletions app/src/main/java/xyz/mxlei/app/ui/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
package xyz.mxlei.app.ui;

import android.content.Intent;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import xyz.mxlei.app.BR;
import xyz.mxlei.app.R;
import xyz.mxlei.app.databinding.ActivityMainBinding;
import xyz.mxlei.mvvmx.base.BaseActivity;

Expand All @@ -17,23 +10,15 @@
*/
public class MainActivity extends BaseActivity<ActivityMainBinding, MainViewModel> {

@Override
public int initContentView(Bundle savedInstanceState) {
return R.layout.activity_main;
}

/**
* 初始化ViewModel的id
*
* @return BR的id
*/
@Override
public int initVariableId() {
return BR.viewmodel;
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable @org.jetbrains.annotations.Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
}
Loading

0 comments on commit fea54cf

Please sign in to comment.