依赖注入框架 -- Dagger2
2020-01-16 本文已影响0人
TomyZhang
一、概念
Dagger2是一个依赖注入框架,主要作用是对象的管理,目的是降低程序耦合。
二、基本使用
//build.gradle(project)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
//build.gradle(module)
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.0"
defaultConfig {
applicationId "com.example.sourcecodetest"
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.google.dagger:dagger:2.11'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
}
//ClassA
public class ClassA {
private static final String TAG = "ClassA";
private ClassB classB;
public ClassA(ClassB classB) {
this.classB = classB;
}
public void eat() {
Log.d(TAG , "zwm, ClassA eat");
classB.eat();
}
}
//ClassB
public class ClassB {
private static final String TAG = "ClassB";
public void eat() {
Log.d(TAG , "zwm, ClassB eat");
}
}
//MainModule
//第一步 添加@Module 注解
@Module
public class MainModule {
//第二步 使用Provider 注解 实例化对象
@Provides
ClassA provideClassA(ClassB classB) {
return new ClassA(classB); //构造ClassA对象需要引入ClassB对象
}
/***
* 构造方法需要其他参数时候
*
* @return
*/
@Provides
ClassB provideClassB() {
return new ClassB(); //构造ClassB对象
}
}
//MainComponent
//第一步 添加@Component
//第二步 添加module
@Component(modules = {MainModule.class})
public interface MainComponent {
//第三步 写一个方法 绑定Activity /Fragment
void inject(MainActivity activity);
}
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
/***
* 第二步 使用Inject 注解,获取到ClassA 对象的实例
*/
@Inject
ClassA classA;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "zwm, onCreate");
/***
* 第一步 添加依赖关系
*/
//第一种方式
DaggerMainComponent.create().inject(this);
//第二种方式
//DaggerMainComponent.builder().build().inject(this);
/***
* 第三步 调用ClassA 对象的方法
*/
classA.eat();
}
}
//输出log
2020-01-14 10:44:54.394 21599-21599/com.example.sourcecodetest D/MyApplication: zwm, onCreate
2020-01-14 10:44:57.282 21599-21599/com.example.sourcecodetest D/MainActivity: zwm, onCreate
2020-01-14 10:44:57.284 21599-21599/com.example.sourcecodetest D/ClassA: zwm, ClassA eat
2020-01-14 10:44:57.284 21599-21599/com.example.sourcecodetest D/ClassB: zwm, ClassB eat
三、模块之间的依赖关系
模块与模块之间的联系
@Module(includes = {BModule.class}) //includes引入
public class AModule {
@Provides
ClassA provideClassA() {
return new ClassA();
}
}
Dagger2会先在AMoudule中寻找对象,如果没找到,会去BModule中寻找对象,如果还是没有,那么就抛出异常。
一个Component应用多个Module
@Component(modules = {AModule.class, BModule.class})
public interface MainComponent {
void inject(MainActivity activity);
}
dependencies依赖其他Component
@Component(modules = {MainModule.class}, dependencies = AppComponent.class)
public interface MainComponent {
void inject(MainActivity activity);
}
四、@Named注解
//ClassA
public class ClassA {
private static final String TAG = "ClassA";
private String str;
public ClassA(String str) {
this.str = str;
}
public void eat() {
Log.d(TAG , "zwm, ClassA eat: " + str);
}
}
//MainModule
//第一步 添加@Module 注解
@Module
public class MainModule {
//第二步 使用Provider 注解 实例化对象
@Named("dev")
@Provides
ClassA provideDEVClassA() {
return new ClassA("dev");
}
@Named("prd")
@Provides
ClassA providePRDClassA() {
return new ClassA("prd");
}
}
//MainComponent
//第一步 添加@Component
//第二步 添加module
@Component(modules = {MainModule.class})
public interface MainComponent {
//第三步 写一个方法 绑定Activity /Fragment
void inject(MainActivity activity);
}
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
/***
* 第二步 使用Inject 注解,获取到ClassA 对象的实例
*/
@Named("dev")
@Inject
ClassA devClassA;
@Named("prd")
@Inject
ClassA prdClassA;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "zwm, onCreate");
/***
* 第一步 添加依赖关系
*/
//第一种方式
DaggerMainComponent.create().inject(this);
//第二种方式
//DaggerMainComponent.builder().build().inject(this);
/***
* 第三步 调用ClassA 对象的方法
*/
devClassA.eat();
prdClassA.eat();
}
}
//输出log
2020-01-14 11:44:04.541 25702-25702/com.example.sourcecodetest D/MyApplication: zwm, onCreate
2020-01-14 11:44:05.069 25702-25702/com.example.sourcecodetest D/MainActivity: zwm, onCreate
2020-01-14 11:44:05.070 25702-25702/com.example.sourcecodetest D/ClassA: zwm, ClassA eat: dev
2020-01-14 11:44:05.070 25702-25702/com.example.sourcecodetest D/ClassA: zwm, ClassA eat: prd
五、@Singleton注解(局部单例)
//ClassA
public class ClassA {
private static final String TAG = "ClassA";
public void eat() {
Log.d(TAG , "zwm, ClassA eat");
}
}
//MainModule
//第一步 添加@Module 注解
@Module
public class MainModule {
//第二步 使用Provider 注解 实例化对象
@Singleton //单例
@Provides
ClassA provideClassA() {
return new ClassA();
}
}
//MainComponent
//第一步 添加@Component
//第二步 添加module
@Singleton //单例
@Component(modules = {MainModule.class})
public interface MainComponent {
//第三步 写一个方法 绑定Activity /Fragment
void inject(MainActivity activity);
void inject(TestActivity activity);
}
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
/***
* 第二步 使用Inject 注解,获取到ClassA 对象的实例
*/
@Inject
ClassA classA1;
@Inject
ClassA classA2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "zwm, onCreate");
/***
* 第一步 添加依赖关系
*/
//第一种方式
DaggerMainComponent.create().inject(this);
//第二种方式
//DaggerMainComponent.builder().build().inject(this);
/***
* 第三步 打印ClassA 对象
*/
Log.d(TAG, "zwm, classA1: " + classA1);
Log.d(TAG, "zwm, classA2: " + classA2);
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
}
}
//TestActivity
public class TestActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
/***
* 第二步 使用Inject 注解,获取到ClassA 对象的实例
*/
@Inject
ClassA testClassA;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
/***
* 第一步 添加依赖关系
*/
//第一种方式
DaggerMainComponent.create().inject(this);
//第二种方式
//DaggerMainComponent.builder().build().inject(this);
/***
* 第三步 打印ClassA 对象
*/
Log.d(TAG, "zwm, testClassA: " + testClassA);
}
}
//输出log
2020-01-14 14:12:22.436 2271-2271/com.example.sourcecodetest D/MyApplication: zwm, onCreate
2020-01-14 14:12:23.944 2271-2271/com.example.sourcecodetest D/MainActivity: zwm, onCreate
2020-01-14 14:12:23.946 2271-2271/com.example.sourcecodetest D/MainActivity: zwm, classA1: com.example.sourcecodetest.ClassA@be46cde
2020-01-14 14:12:23.947 2271-2271/com.example.sourcecodetest D/MainActivity: zwm, classA2: com.example.sourcecodetest.ClassA@be46cde
2020-01-14 14:12:25.971 2271-2271/com.example.sourcecodetest D/MainActivity: zwm, onCreate
2020-01-14 14:12:25.972 2271-2271/com.example.sourcecodetest D/MainActivity: zwm, testClassA: com.example.sourcecodetest.ClassA@e373ba7 //不同的Activity,持有的单例对象不同
注意:
- Module中有单例对象,相应的Component也必须为单例。
- 单例对象只能在同一个Activity中有效,不同的Activity持有的对象不同。
六、自定义Scope(全局单例)
//ClassA
public class ClassA {
private static final String TAG = "ClassA";
public void eat() {
Log.d(TAG , "zwm, ClassA eat");
}
}
//ActivityScope
@Scope
@Retention(RUNTIME)
public @interface ActivityScope {
}
//BaseModule
@Module
public class BaseModule {
@Singleton
@Provides
ClassA provideClassA() {
return new ClassA();
}
}
//BaseComponent
@Singleton
@Component(modules = BaseModule.class)
public interface BaseComponent {
ClassA provideClassA();
}
//MainComponent
@ActivityScope
@Component(dependencies = BaseComponent.class)
public interface MainComponent {
void inject(MainActivity activity);
void inject(TestActivity activity);
}
//MyApplication
public class MyApplication extends Application {
private static final String TAG = "MyApplication";
private BaseComponent baseComponent;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "zwm, onCreate");
baseComponent = DaggerBaseComponent.builder().baseModule(new BaseModule()).build();
}
public BaseComponent getBaseComponent() {
return baseComponent;
}
}
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Inject
ClassA classA1;
@Inject
ClassA classA2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "zwm, onCreate");
DaggerMainComponent.builder()
.baseComponent(((MyApplication)getApplication()).getBaseComponent())
.build()
.inject(this);
Log.d(TAG, "zwm, classA1: " + classA1);
Log.d(TAG, "zwm, classA2: " + classA2);
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
}
}
//TestActivity
public class TestActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Inject
ClassA testClassA;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
DaggerMainComponent.builder()
.baseComponent(((MyApplication)getApplication()).getBaseComponent())
.build()
.inject(this);
Log.d(TAG, "zwm, testClassA: " + testClassA);
}
}
//输出log
2020-01-15 10:53:07.127 32085-32085/? D/MyApplication: zwm, onCreate
2020-01-15 10:53:07.376 32085-32085/? D/MainActivity: zwm, onCreate
2020-01-15 10:53:07.377 32085-32085/? D/MainActivity: zwm, classA1: com.example.sourcecodetest.ClassA@5f1a667
2020-01-15 10:53:07.377 32085-32085/? D/MainActivity: zwm, classA2: com.example.sourcecodetest.ClassA@5f1a667
2020-01-15 10:53:07.616 32085-32085/? D/MainActivity: zwm, onCreate
2020-01-15 10:53:07.616 32085-32085/? D/MainActivity: zwm, testClassA: com.example.sourcecodetest.ClassA@5f1a667 //不同的Activity,持有的单例对象相同
七、Subcomponent
//ClassA
public class ClassA {
private static final String TAG = "ClassA";
public void eat() {
Log.d(TAG , "zwm, ClassA eat");
}
}
//ClassB
public class ClassB {
private static final String TAG = "ClassB";
public void eat() {
Log.d(TAG , "zwm, ClassB eat");
}
}
//MainModule
@Module
public class MainModule {
@Provides
ClassA provideClassA() {
return new ClassA();
}
}
//TestSubModule
@Module
public class TestSubModule {
@Provides
ClassB provideClassB() {
return new ClassB();
}
}
//TestSubComponent
@Subcomponent(modules = TestSubModule.class)
public interface TestSubComponent {
void inject(MainActivity activity);
}
//MainComponent
@Component(modules = {MainModule.class})
public interface MainComponent {
TestSubComponent add(TestSubModule module);
}
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Inject
ClassA classA;
@Inject
ClassB classB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "zwm, onCreate");
DaggerMainComponent.builder()
.mainModule(new MainModule())
.build()
.add(new TestSubModule())
.inject(this);
classA.eat();
classB.eat();
}
}
//输出log
2020-01-15 14:00:27.176 9791-9791/com.example.sourcecodetest D/MyApplication: zwm, onCreate
2020-01-15 14:00:27.624 9791-9791/com.example.sourcecodetest D/MainActivity: zwm, onCreate
2020-01-15 14:00:27.626 9791-9791/com.example.sourcecodetest D/ClassA: zwm, ClassA eat
2020-01-15 14:00:27.626 9791-9791/com.example.sourcecodetest D/ClassB: zwm, ClassB eat
八、Lazy和Provider
//ClassA
public class ClassA {
private static final String TAG = "ClassA";
public void eat() {
Log.d(TAG , "zwm, ClassA eat");
}
}
//MainModule
@Module
public class MainModule {
@Provides
ClassA provideClassA() {
return new ClassA();
}
}
//MainComponent
@Component(modules = {MainModule.class})
public interface MainComponent {
void inject(MainActivity activity);
}
//MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Inject
Lazy<ClassA> lazyClassA;
@Inject
Provider<ClassA> providerClassA;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "zwm, onCreate");
DaggerMainComponent.builder().build().inject(this);
ClassA classA = lazyClassA.get(); //调用Lazy#get方法后才创建ClassA对象,以后每次调用Lazy#get方法会得到同一个ClassA对象
Log.d(TAG, "zwm, classA: " + classA);
classA.eat();
ClassA classA2 = lazyClassA.get();
Log.d(TAG, "zwm, classA2: " + classA2);
classA2.eat();
ClassA classA3 = providerClassA.get(); //调用Provider#get方法后才创建ClassA对象,以后每次调用Provider#get方法会再强制调用Module的Provides方法,并根据Provides方法具体实现的不同,可能返回相同的对象,也可能不同。
Log.d(TAG, "zwm, classA3: " + classA3);
classA3.eat();
ClassA classA4 = providerClassA.get();
Log.d(TAG, "zwm, classA4: " + classA4);
classA4.eat();
}
}
//输出log
2020-01-15 14:29:10.108 11557-11557/com.example.sourcecodetest D/MyApplication: zwm, onCreate
2020-01-15 14:29:10.517 11557-11557/com.example.sourcecodetest D/MainActivity: zwm, onCreate
2020-01-15 14:29:10.518 11557-11557/com.example.sourcecodetest D/MainActivity: zwm, classA: com.example.sourcecodetest.ClassA@5f1a667
2020-01-15 14:29:10.518 11557-11557/com.example.sourcecodetest D/ClassA: zwm, ClassA eat
2020-01-15 14:29:10.518 11557-11557/com.example.sourcecodetest D/MainActivity: zwm, classA2: com.example.sourcecodetest.ClassA@5f1a667
2020-01-15 14:29:10.518 11557-11557/com.example.sourcecodetest D/ClassA: zwm, ClassA eat
2020-01-15 14:29:10.518 11557-11557/com.example.sourcecodetest D/MainActivity: zwm, classA3: com.example.sourcecodetest.ClassA@3416c14
2020-01-15 14:29:10.518 11557-11557/com.example.sourcecodetest D/ClassA: zwm, ClassA eat
2020-01-15 14:29:10.518 11557-11557/com.example.sourcecodetest D/MainActivity: zwm, classA4: com.example.sourcecodetest.ClassA@d414cbd
2020-01-15 14:29:10.518 11557-11557/com.example.sourcecodetest D/ClassA: zwm, ClassA eat
九、MVP + Dagger2
//build.gradle(project)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
//build.gradle(module)
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.0"
defaultConfig {
applicationId "com.example.sourcecodetest"
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.google.dagger:dagger:2.11'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
}
//AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sourcecodetest">
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
//BaseActivity
public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity {
private static final String TAG = "BaseActivity";
@Inject
protected T presenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "zwm, onCreate");
initInject();
if(presenter != null) {
presenter.attachView(this);
}
}
@Override
protected void onDestroy() {
Log.d(TAG, "zwm, onDestroy");
if(presenter != null) {
presenter.detachView();
presenter = null;
}
super.onDestroy();
}
protected abstract void initInject();
}
//BasePresenter
public abstract class BasePresenter<T extends BaseActivity, U extends BaseModel> {
private static final String TAG = "BasePresenter";
protected T view;
@Inject
protected U model;
public void attachView(T view) {
Log.d(TAG, "zwm, attachView");
this.view = view;
initInject();
if(model != null) {
model.attachPresenter(this);
}
}
public void detachView() {
Log.d(TAG, "zwm, detachView");
this.view = null;
if(model != null) {
model.detachPresenter();
model = null;
}
}
protected abstract void initInject();
}
//BaseModel
public abstract class BaseModel<T extends BasePresenter> {
private static final String TAG = "BaseModel";
protected T presenter;
public void attachPresenter(T presenter) {
Log.d(TAG, "zwm, attachPresenter");
this.presenter = presenter;
}
public void detachPresenter() {
Log.d(TAG, "zwm, detachPresenter");
this.presenter = null;
}
}
//MainActivity
public class MainActivity extends BaseActivity<MainPresenter> {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "zwm, onCreate");
presenter.getData();
}
@Override
protected void initInject() {
Log.d(TAG, "zwm, initInject");
DaggerMainComponent.builder().build().inject(this);
}
public void updateUI() {
Log.d(TAG, "zwm, updateUI");
}
}
//MainPresenter
public class MainPresenter extends BasePresenter<MainActivity, MainModel> {
private static final String TAG = "MainPresenter";
@Override
protected void initInject() {
Log.d(TAG, "zwm, initInject");
DaggerMainComponent.builder().build().inject(this);
}
public void getData() {
Log.d(TAG, "zwm, getData");
model.getData();
}
public void onDataGet() {
Log.d(TAG, "zwm, onDataGet");
view.updateUI();
}
}
//MainModel
public class MainModel extends BaseModel<MainPresenter> {
private static final String TAG = "MainModel";
public void getData() {
Log.d(TAG, "zwm, getData");
presenter.onDataGet();
}
}
//MainModule
@Module
public class MainModule {
private static final String TAG = "MainModule";
@Provides
MainPresenter provideMainPresenter() {
Log.d(TAG, "zwm, provideMainPresenter");
return new MainPresenter();
}
@Provides
MainModel provideMainModel() {
Log.d(TAG, "zwm, provideMainModel");
return new MainModel();
}
}
//MainComponent
@Component(modules = {MainModule.class})
public interface MainComponent {
void inject(MainActivity activity);
void inject(MainPresenter presenter);
}
//输出log
2020-01-16 09:36:57.439 25555-25555/com.example.sourcecodetest D/MyApplication: zwm, onCreate
2020-01-16 09:36:57.651 25555-25555/com.example.sourcecodetest D/BaseActivity: zwm, onCreate
2020-01-16 09:36:57.651 25555-25555/com.example.sourcecodetest D/MainActivity: zwm, initInject
2020-01-16 09:36:57.652 25555-25555/com.example.sourcecodetest D/MainModule: zwm, provideMainPresenter
2020-01-16 09:36:57.653 25555-25555/com.example.sourcecodetest D/BasePresenter: zwm, attachView
2020-01-16 09:36:57.653 25555-25555/com.example.sourcecodetest D/MainPresenter: zwm, initInject
2020-01-16 09:36:57.653 25555-25555/com.example.sourcecodetest D/MainModule: zwm, provideMainModel
2020-01-16 09:36:57.653 25555-25555/com.example.sourcecodetest D/BaseModel: zwm, attachPresenter
2020-01-16 09:36:57.851 25555-25555/com.example.sourcecodetest D/MainActivity: zwm, onCreate
2020-01-16 09:36:57.851 25555-25555/com.example.sourcecodetest D/MainPresenter: zwm, getData
2020-01-16 09:36:57.851 25555-25555/com.example.sourcecodetest D/MainModel: zwm, getData
2020-01-16 09:36:57.851 25555-25555/com.example.sourcecodetest D/MainPresenter: zwm, onDataGet
2020-01-16 09:36:57.851 25555-25555/com.example.sourcecodetest D/MainActivity: zwm, updateUI