Android MVP架构搭建
让我们从零开始搭建一个通用的MVP架构
统一依赖和组件化
我们可以把依赖库,还有一些定义的版本好,写成统一的config.gradle:
//配置版本号以及依赖库
ext {
android = [
applicationId : "com.linrh.granary",
compileSdkVersion : 28,
minSdkVersion : 19,
targetSdkVersion : 28,
buildToolsVersion : "28.0.3",
versionCode : 1,
versionName : "1.0.1",
]
//配置java版本
compileOptions = [
sourceCompatibility: JavaVersion.VERSION_1_8,
targetCompatibility: JavaVersion.VERSION_1_8,
]
//项目统一使用到的依赖管理
//使用implementation rootProject.ext.dependencies.xxx的方式进行引用
//比如 implementation rootProject.ext.dependencies.appcompatx
dependencies = [
//自带
appcompatV7 : "com.android.support:appcompat-v7:28.0.0",
design : "com.android.support:design:28.0.0",
recyclerview : "com.android.support:recyclerview-v7:28.0.0",
cardview : "com.android.support:cardview-v7:28.0.0",
annotations : "com.android.support:support-annotations:28.0.0",
multidex : "com.android.support:multidex:1.0.3",
constraintLayout : "com.android.support.constraint:constraint-layout:1.1.3",
flexbox : "com.google.android:flexbox:1.0.0",
//这是androidx的导入包
appcompatx: "androidx.appcompat:appcompat:1.0.2",
materialx: "com.google.android.material:material:1.0.0",
constraintLayoutx: "androidx.constraintlayout:constraintlayout:1.1.3",
annotationx: "androidx.annotation:annotation:1.0.2",
lifecyclex :"androidx.lifecycle:lifecycle-extensions:2.0.0",
//test
androidJUnitRunner : "android.support.test.runner.AndroidJUnitRunner",
junit : "junit:junit:4.12",
runner : "com.android.support.test:runner:1.0.1",
espressocore : "com.android.support.test.espresso:espresso-core:3.1.1",
espressocontrib : "com.android.support.test.espresso:espresso-contrib:3.1.1",
espressointents : "com.android.support.test.espresso:espresso-intents:3.1.1",
//这是androidx的导入包
androidJUnitRunner : "androidx.test.runner.AndroidJUnitRunner",
runnerx :"androidx.test:runner:1.1.1",
espressocorex :"androidx.test.espresso:espresso-core:3.1.1",
espressocontribx : "androidx.test.espresso:espresso-contrib:3.1.1",
espressointentsx : "androidx.test.espresso:espresso-intents:3.1.1",
//kotlin
kotlinCoroutinesCore : "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.0",
//注解
butterknife : "com.jakewharton:butterknife:8.8.1",
butterknifeCompiler : "com.jakewharton:butterknife-compiler:8.8.1",
butterknifeGradlePlugin: "com.jakewharton:butterknife-gradle-plugin:8.8.1",
//rxjava
rxandroid2 : "io.reactivex.rxjava2:rxandroid:2.1.0",
rxjava2 : "io.reactivex.rxjava2:rxjava:2.2.3",
rxlifecycle2 : "com.trello.rxlifecycle2:rxlifecycle:2.2.2",
rxlifecycle2android : "com.trello.rxlifecycle2:rxlifecycle-android:2.2.2",
rxlifecycle2components : "com.trello.rxlifecycle2:rxlifecycle-components:2.2.2",
dagger2 : "com.google.dagger:dagger:2.19",
dagger2android : "com.google.dagger:dagger-android:2.19",
dagger2androidSupport : "com.google.dagger:dagger-android-support:2.19",
dagger2compiler : "com.google.dagger:dagger-compiler:2.19",
dagger2androidProcessor: "com.google.dagger:dagger-android-processor:2.19",
//通信
eventbus : "org.greenrobot:eventbus:3.1.1",
//序列化
gson : "com.google.code.gson:gson:2.8.5",
//图片
glide : "com.github.bumptech.glide:glide:4.8.0",
glideCompiler : "com.github.bumptech.glide:compiler:4.8.0",
glideOkhttp3 : "com.github.bumptech.glide:okhttp3-integration:4.8.0",
picasso : "com.squareup.picasso:picasso:2.5.2",
//网络
rxHttp : "com.github.goweii:RxHttp:2.2.9",
retrofit : "com.squareup.retrofit2:retrofit:2.4.0",
retrofitConverterGson : "com.squareup.retrofit2:converter-gson:2.4.0",
retrofitAdapterRxjava2 : "com.squareup.retrofit2:adapter-rxjava2:2.4.0",
okhttp3 : "com.squareup.okhttp3:3.11.0",
okhttpUrlconnection : "com.squareup.okhttp:okhttp-urlconnection:2.0.0",
//权限
anyPermission : "com.github.goweii:AnyPermission:1.1.2",
//浏览器
agentWeb : "com.just.agentweb:agentweb:4.0.0",
persistentCookieJar : "com.github.franmontiel:PersistentCookieJar:v1.0.1",
//缓存
disklrucache : "com.jakewharton:disklrucache:2.0.2",
//懒加载
lazyfragment : "com.github.goweii.LazyFragment:lazyfragment:1.1.2",
//组件化
arouterApi : "com.alibaba:arouter-api:1.4.1",
arouterCompiler : "com.alibaba:arouter-compiler:1.2.2",
//异常
buglyCrashreport : "com.tencent.bugly:crashreport:3.1.0",
crashActivity : "cat.ereza:customactivityoncrash:2.2.0",
canarydebug : "com.squareup.leakcanary:leakcanary-android:1.6.3",
canaryrelease : "com.squareup.leakcanary:leakcanary-android-no-op:1.6.3",
//布局相关
bravh : "com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.46",
smartRefreshLayout : "com.scwang.smartrefresh:SmartRefreshLayout:1.1.0",
smartRefreshHorizontal : "com.scwang.smartrefresh:SmartRefreshHorizontal:1.0.0-beta-1",
anyDialog : "com.github.goweii:AnyDialog:3.0.3",
anyLayer : "com.github.goweii:AnyLayer:3.2.2",
actionBarEx : "com.github.goweii:ActionBarEx:3.2.1",
percentImageView : "com.github.goweii:PercentImageView:1.0.2",
roundedimageview : "com.makeramen:roundedimageview:2.3.0",
circleimageview : "de.hdodenhof:circleimageview:2.2.0",
magicIndicator : "com.github.hackware1993:MagicIndicator:1.6.0",
photoView : "com.github.chrisbanes:PhotoView:2.1.3",
materialProgressBar : "me.zhanghai.android.materialprogressbar:library:1.4.2",
realtimeBlurView : "com.github.mmin18:realtimeblurview:1.1.2",
banner : "com.youth.banner:banner:1.4.10",
revealLayout : "com.github.goweii:RevealLayout:1.2.1",
anyView : "com.github.goweii:AnyView:1.0.2",
keyboardCompat : "com.github.goweii:KeyboardCompat:1.0.0",
swipelayout : "com.daimajia.swipelayout:library:1.2.0@aar",
multiStateView : "com.github.Kennyc1012:MultiStateView:1.3.2",
pictureSelector : "com.github.goweii:PictureSelector:v2.3.1",
swipeBack : "com.github.goweii:SwipeBack:1.0.7",
tinypinyin : "com.github.promeg:tinypinyin:2.0.3",
blurred : "com.github.goweii:blurred:1.3.0",
lottie : "com.airbnb.android:lottie:2.7.0",
autolayout : "com.zhy:autolayout:1.4.5",
pickerview : "com.contrarywind:Android-PickerView:4.1.3",
photoview : "com.github.chrisbanes:PhotoView:2.1.3",
paginate : "com.github.markomilos:paginate:0.5.1",
autosize : "me.jessyan:autosize:1.1.1",
statusbar : "com.jaeger.statusbarutil:library:1.5.1",
//数据库
greendao : "org.greenrobot:greendao:3.2.2",
greendaoSqlcipher : "net.zetetic:android-database-sqlcipher:3.5.6",
//日志
timber : "com.jakewharton.timber:timber:4.7.1",
]
}
然后再配置好root下面的build.gradle,并引入config.gradle
此处增加了多个地址,可以加快依赖库下载和编译。
//先引入config.gradle
apply from: "config.gradle"
buildscript {
//kotlin support
ext.kotlin_version = '1.3.30'
repositories {
maven { url "https://jitpack.io" }
google()
jcenter()
maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' }
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
// maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
// 华为obs
maven { url 'https://mirrors.huaweicloud.com/repository/maven/huaweicloudsdk' }
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
//自定义组件
dependencies {
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'com.android.tools.build:gradle:3.5.0'
//classpath 'com.android.tools.build:gradle:3.3.2'
//classpath 'com.android.tools.build:gradle:3.2.0'
//classpath "io.realm:realm-gradle-plugin:5.12.0-SNAPSHOT"
//classpath 'com.jakewharton:butterknife-gradle-plugin:9.0.0-SNAPSHOT'
classpath 'com.jakewharton:butterknife-gradle-plugin:10.0.0'
//classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0'
//greendao
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
//kotlin
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
//arouter
classpath "com.alibaba:arouter-register:1.0.2"
//aop
//classpath "com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4"
}
//maven { url uri('./my-plugins/release-plugin') }
}
}
allprojects {
repositories {
maven { url "https://jitpack.io" }
google()
jcenter()
maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' }
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
// maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
// 华为obs
maven { url 'https://mirrors.huaweicloud.com/repository/maven/huaweicloudsdk' }
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
无论是library,还是application,有一些共同的配置,比如编译版本号这些,是通用的,所以再抽出一层 base.gradle
//共有的依赖条件声明到此处。
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode rootProject.ext.android.versionCode
versionName rootProject.ext.android.versionName
testInstrumentationRunner rootProject.ext.dependencies.androidJUnitRunner
}
buildTypes {
release {
debuggable false
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
}
}
compileOptions {
sourceCompatibility rootProject.ext.compileOptions.sourceCompatibility
targetCompatibility rootProject.ext.compileOptions.targetCompatibility
//incremental true
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
//implementation rootProject.ext.dependencies.appcompatx
}
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def requested = details.requested
if (requested.group == 'com.android.support') {
if (!requested.name.startsWith("multidex")) {
details.useVersion rootProject.ext.versions.appcompat
} else {
details.useVersion rootProject.ext.versions.multidex
}
}
}
}
此时,application的gradle可以如此:
apply plugin: 'com.android.application'
apply from: "../basic.gradle"
android {
defaultConfig {
applicationId rootProject.ext.android.applicationId
renderscriptSupportModeEnabled true
ndk {
abiFilters /*'armeabi' ,*/'armeabi-v7a'/*, 'arm64-v8a'*/
}
}
buildTypes {
release {
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFileName = "$applicationId-v${defaultConfig.versionName}.apk"
}
}
}
}
resourcePrefix ""
}
dependencies {
implementation rootProject.ext.dependencies.appcompatx
implementation rootProject.ext.dependencies.constraintLayoutx
implementation rootProject.ext.dependencies.annotationx
implementation rootProject.ext.dependencies.lifecyclex
implementation rootProject.ext.dependencies.materialx
// implementation rootProject.ext.dependencies.appcompatV7
annotationProcessor 'com.jakewharton:butterknife-compiler:10.0.0'
implementation 'com.jakewharton:butterknife:10.0.0'
implementation rootProject.ext.dependencies.eventbus
// implementation rootProject.ext.dependencies.cardview
// implementation rootProject.ext.dependencies.flexbox
// implementation rootProject.ext.dependencies.realtimeBlurView
// implementation rootProject.ext.dependencies.agentWeb
// implementation rootProject.ext.dependencies.banner
// implementation rootProject.ext.dependencies.persistentCookieJar
// implementation rootProject.ext.dependencies.revealLayout
// implementation rootProject.ext.dependencies.keyboardCompat
// implementation rootProject.ext.dependencies.swipelayout
// implementation rootProject.ext.dependencies.disklrucache
// implementation rootProject.ext.dependencies.multiStateView
// implementation rootProject.ext.dependencies.pictureSelector
// implementation rootProject.ext.dependencies.buglyCrashreport
// implementation rootProject.ext.dependencies.crashActivity
}
library可以这么写:
apply plugin: 'com.android.library'
apply from: "../basic.gradle"
android {
}
dependencies {
implementation rootProject.ext.dependencies.appcompatx
}
这时候,如果有实现library可以配置成为application,直接编译运行,该怎么弄呢?
在settings.gradle里面,新增
#isBuildModule 为 true 时可以使每个组件独立运行, false 则可以将所有组件集成到宿主 App 中
isBuildModule=false
在模块的build.gradle中改动为:
if (isBuildModule.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
apply from: "../basic.gradle"
android {
defaultConfig {
if (isBuildModule.toBoolean()) {
applicationId "com.linrh.hellotest"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation rootProject.ext.dependencies.appcompatx
implementation rootProject.ext.dependencies.constraintLayoutx
testImplementation rootProject.ext.dependencies.junit
androidTestImplementation rootProject.ext.dependencies.runnerx
androidTestImplementation rootProject.ext.dependencies.espressocorex
}
此时就可以编译为独立的APP了。
MVP框架搭建
MVP框架简单来说,就是M层和V层中间抽像了一层接口层P层,P层持有V层的引用以及M层的对象,然后充当中间的媒介。
可以抽象出统一的模版
抽象出view
import android.content.Context;
/**
* 主要界面的基础接口
*/
public interface IMvpView {
Context getContext();
void showLoadingDialog();
void dismissLoadingDialog();
void clearLoading();
}
抽象出对于的P
package com.linrh.base.mvp;
import android.content.Context;
public abstract class MvpPresenter <V extends IMvpView>{
protected Context context;
private V baseView;
public void attach(V baseView) {
this.baseView = baseView;
context = baseView.getContext();
}
public void detach() {
baseView = null;
context = null;
}
public V getBaseView() {
return baseView;
}
public boolean isAttach() {
return baseView != null;
}
public Context getContext() {
return context;
}
public void showLoadingDialog() {
if (baseView != null) {
baseView.showLoadingDialog();
}
}
public void dismissLoadingDialog() {
if (baseView != null) {
baseView.dismissLoadingDialog();
}
}
}
可以设定一个统一的Activity
package com.linrh.base.mvp;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.Nullable;
public abstract class MvpActivity<P extends MvpPresenter> extends Activity
implements IMvpView{
public P presenter;
/**
* 初始化窗口
*/
protected void initWindow() {
}
/**
* 获取布局资源文件。
* 返回布局文件的ID
*/
protected abstract int getLayoutId();
/**
* 初始化presenter
*/
@Nullable
protected abstract P initPresenter();
/**
* 初始化控件
*/
protected abstract void initView();
/**
* 绑定数据
*/
protected abstract void loadData();
/**
* 初始化
*/
protected void initialize() {
initView();
loadData();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initWindow();
if (getLayoutId() > 0) {
setContentView(getLayoutId());
}
presenter = initPresenter();
if (presenter != null) {
//V 与 P 绑定
presenter.attach(this);
}
initialize();
}
@Override
protected void onDestroy() {
if (presenter != null) {
presenter.detach();
}
super.onDestroy();
}
@Override
public Context getContext() {
return getActivity();
}
protected Activity getActivity() {
return this;
}
}
或者一个统一的fragment
package com.linrh.base.mvp;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public abstract class MvpFragment<P extends MvpPresenter> extends Fragment
implements IMvpView{
/**
* 界面布局
*/
protected View mRootView = null;
/**
* 标识界面是否创建
*/
protected boolean mViewCreated = false;
public P presenter;
/**
* 初始化窗口
*/
protected void initWindow() {
}
/**
* 获取布局资源文件。
* 返回布局文件的ID
*/
protected abstract int getLayoutId();
/**
* 初始化presenter
*/
@Nullable
protected abstract P initPresenter();
/**
* 初始化控件
*/
protected abstract void initView();
/**
* 绑定数据
*/
protected abstract void loadData();
/**
* 初始化
*/
protected void initialize() {
initView();
loadData();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
/**
* 初始化界面
*/
if (mRootView == null) {
final int layoutId = getLayoutId();
if (layoutId > 0) {
mRootView = inflater.inflate(getLayoutId(), container, false);
}
}
mViewCreated = true;
return mRootView;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
presenter = initPresenter();
if (presenter != null) {
presenter.attach(this);
}
initialize();
}
@Override
public void onDestroyView() {
if (presenter != null) {
presenter.detach();
}
super.onDestroyView();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public Context getContext() {
return getActivity();
}
public Fragment getFragment() {
return this;
}
}
为了便于理解,此处回顾下fragment的生命周期
- setUserVisibleHint():设置Fragment可见或者不可见时会调用此方法。在该方法里面可以通过调用getUserVisibleHint()获得Fragment的状态是可见还是不可见的,如果可见则进行懒加载操作。
- onAttach():执行该方法时,Fragment与Activity已经完成绑定,该方法有一个Activity类型的参数,代表绑定的Activity,这时候你可以执行诸如mActivity = activity的操作。
- onCreate():初始化Fragment。可通过参数savedInstanceState获取之前保存的值。
- onCreateView():初始化Fragment的布局。加载布局和findViewById的操作通常在此函数内完成,但是不建议执行耗时的操作,比如读取数据库数据列表。
- onActivityCreated():执行该方法时,与Fragment绑定的Activity的onCreate方法已经执行完成并返回,在该方法内可以进行与Activity交互的UI操作,所以在该方法之前Activity的onCreate方法并未执行完成,如果提前进行交互操作,会引发空指针异常。
- onStart():执行该方法时,Fragment由不可见变为可见状态。
- onResume():执行该方法时,Fragment处于活动状态,用户可与之交互。
- onPause():执行该方法时,Fragment处于暂停状态,但依然可见,用户不能与之交互。
- onSaveInstanceState():保存当前Fragment的状态。该方法会自动保存Fragment的状态,比如EditText键入的文本,即使Fragment被回收又重新创建,一样能恢复EditText之前键入的文本。
- onStop():执行该方法时,Fragment完全不可见。
- onDestroyView():销毁与Fragment有关的视图,但未与Activity解除绑定,依然可以通过onCreateView方法重新创建视图。通常在ViewPager+Fragment的方式下会调用此方法。
- onDestroy():销毁Fragment。通常按Back键退出或者Fragment被回收时调用此方法。
- onDetach():解除与Activity的绑定。在onDestroy方法之后调用。
一般Activity继承这个MvpActivity后,可能会用到ButterKnife等,可以在封装一层BaseActivity
package com.linrh.base.base;
import com.linrh.base.mvp.MvpActivity;
import com.linrh.base.ui.LoadingDialog;
import org.greenrobot.eventbus.EventBus;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* @author Cuizhen
* @version v1.0.0
* @date 2018/4/4-下午1:23
*/
public abstract class BaseActivity<P extends BasePresenter> extends MvpActivity<P> {
private LoadingDialog mLoadingDialog = null;
private Unbinder mUnbinder = null;
/**
* 是否注册事件分发,默认不绑定
*/
protected boolean isRegisterEventBus() {
return false;
}
@Override
protected void initialize() {
mUnbinder = ButterKnife.bind(this);
if (isRegisterEventBus()) {
EventBus.getDefault().register(this);
}
super.initialize();
}
@Override
protected void onDestroy() {
clearLoading();
super.onDestroy();
if (isRegisterEventBus()) {
EventBus.getDefault().unregister(this);
}
if (mUnbinder != null) {
mUnbinder.unbind();
}
}
@Override
public void showLoadingDialog() {
if (mLoadingDialog == null) {
mLoadingDialog = LoadingDialog.with(getContext());
}
mLoadingDialog.show();
}
@Override
public void dismissLoadingDialog() {
if (mLoadingDialog != null) {
mLoadingDialog.dismiss();
}
}
@Override
public void clearLoading() {
if (mLoadingDialog != null) {
mLoadingDialog.clear();
}
mLoadingDialog = null;
}
}
isRegisterEventBus函数,可以指定是否需要EventBus.
BasePresenter:
package com.linrh.base.base;
import com.linrh.base.mvp.MvpPresenter;
/**
* 此处可以用来做一些生命周期的控制
* 比如对rxjava的请求作为统一的管理
* @param <V>
*/
public class BasePresenter<V extends BaseView> extends MvpPresenter<V> {
@Override
public void attach(V baseView) {
super.attach(baseView);
}
@Override
public void detach() {
super.detach();
}
}
BaseView:
package com.linrh.base.base;
import com.linrh.base.mvp.IMvpView;
public interface BaseView extends IMvpView {
}
现在我们开始创建一个模块来实现登录的功能。
首先设置下目录
新建LoginView,添加自定义的界面动作
package com.linrh.granary.module.login.view;
import android.content.Context;
import com.linrh.base.base.BaseView;
public interface LoginView extends BaseView {
void loginSuccess(int code, LoginBean data);
void loginFailed(int code, String msg);
}
定义模块的presenter
package com.linrh.granary.module.login.presenter;
import com.linrh.base.base.BasePresenter;
import com.linrh.granary.module.login.model.LoginBean;
import com.linrh.granary.module.login.view.LoginView;
public class LoginPresenter extends BasePresenter<LoginView> {
public void login(String userName, String password){
//开始请求
showLoadingDialog();
//请求成功
if (isAttach()){
getBaseView().loginSuccess(00,new LoginBean());
}
//失败
if (isAttach()){
getBaseView().loginFailed(00,"fail");
}
//结束
dismissLoadingDialog();
}
}
其中根据需求,完成相应的逻辑操作。最后实现View层
package com.linrh.granary.module.login.activity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import androidx.annotation.Nullable;
import com.linrh.base.base.BaseActivity;
import com.linrh.granary.R;
import com.linrh.granary.module.login.model.LoginBean;
import com.linrh.granary.module.login.presenter.LoginPresenter;
import com.linrh.granary.module.login.view.LoginView;
public class LoginActivity extends BaseActivity<LoginPresenter> implements LoginView {
ProgressBar loadingProgressBar;
@Override
protected int getLayoutId() {
return R.layout.activity_login;
}
@Nullable
@Override
protected LoginPresenter initPresenter() {
return new LoginPresenter();
}
@Override
protected void initView() {
final EditText usernameEditText = findViewById(R.id.username);
final EditText passwordEditText = findViewById(R.id.password);
final Button loginButton = findViewById(R.id.login);
loadingProgressBar = findViewById(R.id.loading);
loginButton.setEnabled(true);
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
presenter.login(usernameEditText.getText().toString().trim(),
passwordEditText.getText().toString().trim());
}
});
}
@Override
protected void loadData() {
}
@Override
public void loginSuccess(int code, LoginBean data) {
}
@Override
public void loginFailed(int code, String msg) {
}
@Override
public void showLoadingDialog() {
//super.showLoadingDialog();
loadingProgressBar.setVisibility(View.VISIBLE);
}
@Override
public void dismissLoadingDialog() {
//super.dismissLoadingDialog();
loadingProgressBar.setVisibility(View.GONE);
}
}
简单来说,就是mvp定义基本关系,base初始化一些界面通用的注解和等待弹窗。最上层的MVP,用来做实际上的操作。