Android MVP和Dagger2
在本教程中,我们将在Android应用程序中与Dagger2一起实现MVP模式。
建议一起使用这些设计模式概念之前,分别进行探讨。
Android MVP和Dagger2
我们知道,MVP是基于关注点分离的。
MVP模式将我们的代码分为三层-模型,视图和演示者。
演示者充当模型和视图之间的桥梁。
没有演示者,模型和视图将无法相互通信。
演示者模型,演示者视图使用接口进行通信。
Dagger2是Square开发的依赖注入库。
我们没有在类中创建依赖关系,而是通过使用Dagger2核心结构-"模块","组件","注入"和"提供"来提供依赖。
使用Dagger2批注,编译器会在编译时自动构建Dagger类。
MVP + Dagger2 =开始我们的旅程,以遵循SOLID原则编写简洁的代码。
因此,在以下部分中,我们将从本教程的MVP Android Studio项目中使用Dagger2。
这将使我们更清楚Dagger2如何与MVP配合使用。
Android MVP Dagger2项目结构
模型–项目的模型类。
视图–我们的活动就是这里的视图。
Presenter – Presenter类,它最终告诉Activity如何处理View。
MainContract.java –包括模型,视图和演示者的接口。
di –包括依赖项注入– Dagger2类。
不要忘记在build.gradle文件中添加以下依赖项。
annotationProcessor 'com.google.dagger:dagger-compiler:2.13' implementation 'com.google.dagger:dagger:2.13'
Android MVP Dagger2代码
让我们看看在MainContract.java类中为MVP类定义的接口。
package com.theitroad.mvpdagger2; public interface MainContract { interface ViewCallBack { void showProgress(); void hideProgress(); void setQuote(String string); } interface ModelCallBack { interface OnFinishedListener { void onFinished(String string); } void getNextQuote(OnFinishedListener onFinishedListener); } interface PresenterCallBack { void onButtonClick(); void onDestroy(); } }
因此,视图具有用于设置字符串,显示或者隐藏ProgressBar的界面。
该模型具有一个onFinished接口,该接口在处理程序间隔成功之后触发。
演示者控制活动按钮的单击和onDestroy()生命周期。
模型
package com.theitroad.mvpdagger2.model; import android.os.Handler; import com.theitroad.mvpdagger2.MainContract; import java.util.Arrays; import java.util.List; import java.util.Random; public class Model implements MainContract.ModelCallBack { @Override public void getNextQuote(final MainContract.ModelCallBack.OnFinishedListener listener) { new Handler().postDelayed(new Runnable() { @Override public void run() { listener.onFinished(getRandomQuote()); } }, 1200); } private List<String> arrayList = Arrays.asList( "Be yourself. everyone else is already taken.", "A room without books is like a body without a soul.", "You only live once, but if you do it right, once is enough.", "Be the change that you wish to see in the world.", "If you tell the truth, you don't have to remember anything." ); private String getRandomQuote() { Random random = new Random(); int index = random.nextInt(arrayList.size()); return arrayList.get(index); } }
演示者实现在MainPresenterImpl.java类中定义。
package com.theitroad.mvpdagger2.presenter; import com.theitroad.mvpdagger2.MainContract; import com.theitroad.mvpdagger2.model.Model; public class MainPresenterImpl implements MainContract.PresenterCallBack, MainContract.ModelCallBack.OnFinishedListener { private MainContract.ViewCallBack mainView; private Model model; public MainPresenterImpl(MainContract.ViewCallBack mainView, Model model) { this.mainView = mainView; this.model = model; } @Override public void onButtonClick() { if (mainView != null) { mainView.showProgress(); } model.getNextQuote(this); } @Override public void onDestroy() { mainView = null; } @Override public void onFinished(String string) { if (mainView != null) { mainView.setQuote(string); mainView.hideProgress(); } } }
迪包
在di包中,我们定义了依赖项注入模块和组件。
我们先来看一下模块。
AppModule.java
package com.theitroad.mvpdagger2.di.module; import android.app.Application; import com.theitroad.mvpdagger2.InitApplication; import javax.inject.Singleton; import dagger.Module; import dagger.Provides; @Module public class AppModule { private InitApplication initApplication; public AppModule(InitApplication initApplication) { this.initApplication = initApplication; } @Provides @Singleton public Application provideApplication() { return initApplication; } }
这在整个项目中提供了一个应用程序实例。
ContextModule.java
package com.theitroad.mvpdagger2.di.module; import android.content.Context; import dagger.Module; import dagger.Provides; @Module public class ContextModule { private Context context; public ContextModule(Context context) { this.context = context; } @Provides public Context provideContext() { return context; } }
提供getApplicationContext()
DataModule.java
package com.theitroad.mvpdagger2.di.module; import com.theitroad.mvpdagger2.model.Model; import dagger.Module; import dagger.Provides; @Module public class DataModule { @Provides public Model provideModelClass() { return new Model(); } }
这为我们提供了Model类的实例。
MvpModule.java
package com.theitroad.mvpdagger2.di.module; import com.theitroad.mvpdagger2.MainContract; import com.theitroad.mvpdagger2.model.Model; import com.theitroad.mvpdagger2.presenter.MainPresenterImpl; import dagger.Module; import dagger.Provides; @Module public class MvpModule { private MainContract.ViewCallBack viewCallBack; public MvpModule(MainContract.ViewCallBack viewCallBack) { this.viewCallBack = viewCallBack; } @Provides public MainContract.ViewCallBack provideView() { return viewCallBack; } @Provides public MainContract.PresenterCallBack providePresenter(MainContract.ViewCallBack view, Model model) { return new MainPresenterImpl(view, model); } }
这提供了MainPresenterImpl.java类的实例。
它使用View的界面和Model类作为构造函数参数。
ActivityScope.java
package com.theitroad.mvpdagger2.di.scope; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.inject.Scope; @Scope @Retention(RetentionPolicy.RUNTIME) public @interface ActivityScope { }
这将设置组件的范围,我们将在后面看到。
AppComponent.java
package com.theitroad.mvpdagger2.di.component; import android.app.Application; import android.content.Context; import com.theitroad.mvpdagger2.InitApplication; import com.theitroad.mvpdagger2.di.module.AppModule; import com.theitroad.mvpdagger2.di.module.ContextModule; import com.theitroad.mvpdagger2.di.module.DataModule; import com.theitroad.mvpdagger2.model.Model; import javax.inject.Singleton; import dagger.Component; @Singleton @Component(modules = {AppModule.class, DataModule.class, ContextModule.class}) public interface AppComponent { void inject(InitApplication initApplication); Context getContext(); Model getFindItemsInteractor(); Application getApplication(); }
这是应用程序级组件。
在整个应用程序中都可以访问这些字段。
ActivityComponent.java
package com.theitroad.mvpdagger2.di.component; import com.theitroad.mvpdagger2.MainContract; import com.theitroad.mvpdagger2.di.module.MvpModule; import com.theitroad.mvpdagger2.di.scope.ActivityScope; import com.theitroad.mvpdagger2.view.MainActivity; import dagger.Component; @ActivityScope @Component(dependencies = AppComponent.class, modules = MvpModule.class) public interface ActivityComponent { void inject(MainActivity mainActivity); MainContract.PresenterCallBack getMainPresenter(); }
该组件用于将Presenter注入到我们的MainActivity中。
下面给出了InitApplication.java的代码:
package com.theitroad.mvpdagger2; import android.app.Application; import android.content.Context; import com.theitroad.mvpdagger2.di.component.AppComponent; import com.theitroad.mvpdagger2.di.component.DaggerAppComponent; import com.theitroad.mvpdagger2.di.module.AppModule; import com.theitroad.mvpdagger2.di.module.ContextModule; import com.theitroad.mvpdagger2.di.module.DataModule; public class InitApplication extends Application { private AppComponent component; public static InitApplication get(Context context) { return (InitApplication) context.getApplicationContext(); } @Override public void onCreate() { super.onCreate(); component = DaggerAppComponent.builder() .appModule(new AppModule(this)) .contextModule(new ContextModule(this)) .dataModule(new DataModule()) .build(); } public AppComponent component() { return component; } }
下面给出了activity_main.xml布局文件的代码。
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="0dp" android:layout_height="wrap_content" android:gravity="center" android:padding="8dp" android:text="Implementing MVP and Dagger2 in this Application." android:textAppearance="?android:attr/textAppearanceSearchResultTitle" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="@android:dimen/notification_large_icon_height" android:text="GET NEXT QUOTE" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" <ProgressBar android:id="@+id/progressBar" style="?android:attr/progressBarStyleLarge" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" </android.support.constraint.ConstraintLayout>
MainActivity.java类的代码如下:
package com.theitroad.mvpdagger2.view; import android.content.Context; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.theitroad.mvpdagger2.InitApplication; import com.theitroad.mvpdagger2.MainContract; import com.theitroad.mvpdagger2.R; import com.theitroad.mvpdagger2.di.component.DaggerActivityComponent; import com.theitroad.mvpdagger2.di.module.MvpModule; import javax.inject.Inject; import static android.view.View.GONE; public class MainActivity extends AppCompatActivity implements MainContract.ViewCallBack { @Inject MainContract.PresenterCallBack presenterCallBack; @Inject Context mContext; private TextView textView; private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DaggerActivityComponent.builder() .appComponent(InitApplication.get(this).component()) .mvpModule(new MvpModule(this)) .build() .inject(this); textView = findViewById(R.id.textView); Button button = findViewById(R.id.button); progressBar = findViewById(R.id.progressBar); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { presenterCallBack.onButtonClick(); } }); } @Override protected void onResume() { super.onResume(); } @Override protected void onDestroy() { super.onDestroy(); presenterCallBack.onDestroy(); } @Override public void showProgress() { progressBar.setVisibility(View.VISIBLE); textView.setVisibility(View.INVISIBLE); } @Override public void hideProgress() { progressBar.setVisibility(GONE); textView.setVisibility(View.VISIBLE); } @Override public void setQuote(String string) { textView.setText(string); Toast.makeText(mContext, "Quote Updated", Toast.LENGTH_SHORT).show(); } }
瞧!我们将Presenter注入到这里而不实例化它。
多亏了Dagger2。