mvp+dagger2

In this tutorial, we’ll be developing an application using MVP, Dagger2, Retrofit and RxJava.

在本教程中,我们将使用MVP , Dagger2 , Retrofit和RxJava开发应用程序。

These days cryptocurrency is the latest fad. So we’ll be creating a cryptocurrency application using the above things.

如今,加密货币是最新的时尚。 因此,我们将使用以上内容创建一个加密货币应用程序。

总览 (Overview)

To proceed further you must have an overview of the Model View Presenter, Dependency Injection, Retrofit and RxJava libraries.
We have covered them individually and in combination with the following tutorial links specified:

要进一步进行操作,您必须具有Model View Presenter,依赖注入,翻新和RxJava库的概述。
我们已经单独介绍了它们,并结合了以下指定的教程链接:

  • Android MVPAndroid MVP
  • Android Dagger2Android Dagger2
  • Android RetrofitAndroid改造
  • Android RxJavaAndroid RxJava
  • Android Dagger2 + RetrofitAndroid Dagger2 +改装
  • Android RxJava + RetrofitAndroid RxJava +改造
  • MVP + Dagger2MVP +匕首2

If you know the basics of the above things, the following example should be an easy ride. Let’s dive right in!

如果您了解上述内容的基础知识,那么下面的示例应该很容易。 让我们潜入吧!

Create a new Android Studio project.

创建一个新的Android Studio项目。

图书馆 (Libaries)

Add the following libraries in your app’s build.gradle file.

在您应用的build.gradle文件中添加以下库。

RxAndroid is just like RxJava. It contains the schedulers and threads for the Android framework.

RxAndroid就像RxJava。 它包含Android框架的调度程序和线程。

项目结构 (Project Structure)

The di package contains the dependency injection – Dagger2 related files. The mvp package consists of the MVP related ones and so on.

di软件包包含依赖项注入– Dagger2相关文件。 mvp软件包包括与MVP相关的软件包,依此类推。

Where and how do we start?
It can get confusing when we are asked to use so many different things in our project.

我们从哪里开始,如何开始?
当要求我们在项目中使用这么多不同的东西时,这可能会造成混乱。

The beginning is always tricky. Once we know the process, everything becomes easy.

开始总是很棘手。 一旦我们知道了过程,一切就变得容易了。

So let’s list down our requirements and how we’ll approach them.

因此,让我们列出我们的要求以及我们将如何处理它们。

Our application would contain a single activity. It would host a RecyclerView to display the data from the API call. For the API call we’ll use Retrofit and RxJava.

我们的应用程序将包含一个活动。 它将托管一个RecyclerView来显示来自API调用的数据。 对于API调用,我们将使用Retrofit和RxJava。

Approach:方法

  • Create your activity and recyclerview xml layouts first. Lock the Design before you code.首先创建您的活动并recyclerview xml布局。 在编码之前,请锁定设计。
  • Create the APIInterface.java class. It defines the API calls to be made.创建APIInterface.java类。 它定义了要进行的API调用。
  • Create the POJO data class which would parse the response from the API call.创建POJO数据类,它将解析来自API调用的响应。
  • Start by creating the Interface for the MVP – MainActivityContract.java.首先为MVP创建接口– MainActivityContract.java。
  • Create the di modules, components, scopes and qualifiers.创建di模块,组件,作用域和限定符。
  • Now create the PresenterImpl.现在创建PresenterImpl。
  • Finally, write the MainActivity and RecyclerViewAdapter classes plugging the Dependencies and the MVP pattern in.最后,编写MainActivity和RecyclerViewAdapter类,将Dependencies和MVP模式插入其中。

布局代码 (Layout code)

activity_main.xml

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"xmlns:tools="https://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><android.support.v7.widget.RecyclerViewandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="match_parent" /><ProgressBarandroid: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>

recycler_view_list_row.xml

recycler_view_list_row.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:id="@+id/constraintLayout"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="16dp"><TextViewandroid:id="@+id/txtCoin"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintBottom_toTopOf="@+id/txtCurrentPrice"app:layout_constraintTop_toTopOf="parent"/><TextViewandroid:id="@+id/txtCurrentPrice"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintTop_toBottomOf="@+id/txtCoin"/><TextViewandroid:id="@+id/txtOneHourChange"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintEnd_toEndOf="parent" /><TextViewandroid:id="@+id/txtOneHour"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginEnd="8dp"android:layout_marginRight="8dp"android:text="1H"app:layout_constraintEnd_toStartOf="@+id/txtOneHourChange"app:layout_constraintTop_toTopOf="@+id/txtOneHourChange" /><TextViewandroid:id="@+id/txt24HourChange"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintTop_toBottomOf="@+id/txtOneHourChange" /><TextViewandroid:id="@+id/txt7Day"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginEnd="8dp"android:layout_marginRight="8dp"android:text="7D"app:layout_constraintEnd_toStartOf="@+id/txt7DayChange"app:layout_constraintTop_toTopOf="@+id/txt7DayChange" /><TextViewandroid:id="@+id/txt24Hour"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginEnd="8dp"android:layout_marginRight="8dp"android:text="24H"app:layout_constraintBottom_toTopOf="@+id/txt7DayChange"app:layout_constraintEnd_toStartOf="@+id/txt24HourChange"app:layout_constraintTop_toTopOf="@+id/txt24HourChange" /><TextViewandroid:id="@+id/txt7DayChange"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintTop_toBottomOf="@+id/txt24HourChange" /></android.support.constraint.ConstraintLayout>

APIInterface.java

APIInterface.java

package com.journaldev.mvpdagger2retroiftrxjava.retrofit;import com.journaldev.mvpdagger2retroiftrxjava.pojo.CryptoData;
import java.util.List;
import retrofit2.http.GET;
import retrofit2.http.Query;
import rx.Observable;public interface APIInterface {@GET("ticker/?")Observable<List<CryptoData>> getData(@Query("limit") String limit);
}

The base URL would be defined in our RetrofitModule.
We’re using this API.

基本URL将在我们的RetrofitModule中定义。
我们正在使用此 API。

CryptoData.java

CryptoData.java

package com.journaldev.mvpdagger2retroiftrxjava.pojo;import com.google.gson.annotations.SerializedName;public class CryptoData {@SerializedName("id")public String id;@SerializedName("name")public String name;@SerializedName("symbol")public String symbol;@SerializedName("rank")public String rank;@SerializedName("price_usd")public String priceUsd;@SerializedName("price_btc")public String priceBtc;@SerializedName("24h_volume_usd")public String _24hVolumeUsd;@SerializedName("market_cap_usd")public String marketCapUsd;@SerializedName("available_supply")public String availableSupply;@SerializedName("total_supply")public String totalSupply;@SerializedName("percent_change_1h")public String percentChange1h;@SerializedName("percent_change_24h")public String percentChange24h;@SerializedName("percent_change_7d")public String percentChange7d;@SerializedName("last_updated")public String lastUpdated;}

MainActivityContract.java
This is the blueprint of our View-Model-Presenter:

MainActivityContract.java
这是我们的View-Model-Presenter的蓝图:

package com.journaldev.mvpdagger2retroiftrxjava.mvp;import com.journaldev.mvpdagger2retroiftrxjava.pojo.CryptoData;
import java.util.List;public interface MainActivityContract {interface View {void showData(List<CryptoData> data);void showError(String message);void showComplete();void showProgress();void hideProgress();}interface Presenter {void loadData();}
}

ActivityScope.java

ActivityScope.java

package com.journaldev.mvpdagger2retroiftrxjava.di.scopes;import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Scope;@Scope
@Retention(RetentionPolicy.CLASS)
public @interface ActivityScope {
}

ApplicationScope.java

ApplicationScope.java

package com.journaldev.mvpdagger2retroiftrxjava.di.scopes;import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Scope;@Scope
@Retention(RetentionPolicy.CLASS)
public @interface ApplicationScope {
}

ActivityContext.java

ActivityContext.java

package com.journaldev.mvpdagger2retroiftrxjava.di.qualifier;import javax.inject.Qualifier;@Qualifier
public @interface ActivityContext {}

ApplicationContext.java

ApplicationContext.java

package com.journaldev.mvpdagger2retroiftrxjava.di.qualifier;import javax.inject.Qualifier;@Qualifier
public @interface ApplicationContext {}

ContextModule.java

ContextModule.java

package com.journaldev.mvpdagger2retroiftrxjava.di.module;import android.content.Context;
import com.journaldev.mvpdagger2retroiftrxjava.di.qualifier.ApplicationContext;
import com.journaldev.mvpdagger2retroiftrxjava.di.scopes.ApplicationScope;
import dagger.Module;
import dagger.Provides;@Module
public class ContextModule {private Context context;public ContextModule(Context context) {this.context = context;}@Provides@ApplicationScope@ApplicationContextpublic Context provideContext() {return context;}
}

MainActivityContextModule.java

MainActivityContextModule.java

package com.journaldev.mvpdagger2retroiftrxjava.di.module;import android.content.Context;import com.journaldev.mvpdagger2retroiftrxjava.MainActivity;
import com.journaldev.mvpdagger2retroiftrxjava.di.qualifier.ActivityContext;
import com.journaldev.mvpdagger2retroiftrxjava.di.scopes.ActivityScope;import dagger.Module;
import dagger.Provides;@Module
public class MainActivityContextModule {private MainActivity mainActivity;public Context context;public MainActivityContextModule(MainActivity mainActivity) {this.mainActivity = mainActivity;context = mainActivity;}@Provides@ActivityScopepublic MainActivity providesMainActivity() {return mainActivity;}@Provides@ActivityScope@ActivityContextpublic Context provideContext() {return context;}}

RetrofitModule.java

RetrofitModule.java

package com.journaldev.mvpdagger2retroiftrxjava.di.module;import com.journaldev.mvpdagger2retroiftrxjava.di.scopes.ApplicationScope;
import com.journaldev.mvpdagger2retroiftrxjava.retrofit.APIInterface;
import dagger.Module;
import dagger.Provides;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;@Module
public class RetrofitModule {@Provides@ApplicationScopeAPIInterface getApiInterface(Retrofit retroFit) {return retroFit.create(APIInterface.class);}@Provides@ApplicationScopeRetrofit getRetrofit(OkHttpClient okHttpClient) {return new Retrofit.Builder().baseUrl("https://api.coinmarketcap.com/v1/").addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).client(okHttpClient).build();}@Provides@ApplicationScopeOkHttpClient getOkHttpCleint(HttpLoggingInterceptor httpLoggingInterceptor) {return new OkHttpClient.Builder().addInterceptor(httpLoggingInterceptor).build();}@Provides@ApplicationScopeHttpLoggingInterceptor getHttpLoggingInterceptor() {HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);return httpLoggingInterceptor;}
}

MainActivityMvpModule.java

MainActivityMvpModule.java

package com.journaldev.mvpdagger2retroiftrxjava.di.module;import com.journaldev.mvpdagger2retroiftrxjava.di.scopes.ActivityScope;
import com.journaldev.mvpdagger2retroiftrxjava.mvp.MainActivityContract;
import dagger.Module;
import dagger.Provides;@Module
public class MainActivityMvpModule {private final MainActivityContract.View mView;public MainActivityMvpModule(MainActivityContract.View mView) {this.mView = mView;}@Provides@ActivityScopeMainActivityContract.View provideView() {return mView;}}

AdapterModule.java

AdapterModule.java

package com.journaldev.mvpdagger2retroiftrxjava.di.module;import com.journaldev.mvpdagger2retroiftrxjava.MainActivity;
import com.journaldev.mvpdagger2retroiftrxjava.RecyclerViewAdapter;
import com.journaldev.mvpdagger2retroiftrxjava.di.scopes.ActivityScope;import dagger.Module;
import dagger.Provides;@Module(includes = {MainActivityContextModule.class})
public class AdapterModule {@Provides@ActivityScopepublic RecyclerViewAdapter getCoinList(RecyclerViewAdapter.ClickListener clickListener) {return new RecyclerViewAdapter(clickListener);}@Provides@ActivityScopepublic RecyclerViewAdapter.ClickListener getClickListener(MainActivity mainActivity) {return mainActivity;}
}

Components are what inject the dependencies from the Modules.

组件是注入来自模块的依赖关系的组件。

ApplicationComponent.java

ApplicationComponent.java

package com.journaldev.mvpdagger2retroiftrxjava.di.component;import android.content.Context;import com.journaldev.mvpdagger2retroiftrxjava.MyApplication;
import com.journaldev.mvpdagger2retroiftrxjava.di.module.ContextModule;
import com.journaldev.mvpdagger2retroiftrxjava.di.module.RetrofitModule;
import com.journaldev.mvpdagger2retroiftrxjava.di.qualifier.ApplicationContext;
import com.journaldev.mvpdagger2retroiftrxjava.di.scopes.ApplicationScope;
import com.journaldev.mvpdagger2retroiftrxjava.retrofit.APIInterface;import dagger.Component;@ApplicationScope
@Component(modules = {ContextModule.class, RetrofitModule.class})
public interface ApplicationComponent {APIInterface getApiInterface();@ApplicationContextContext getContext();void injectApplication(MyApplication myApplication);
}

MainActivityComponent.java

MainActivityComponent.java

package com.journaldev.mvpdagger2retroiftrxjava.di.component;import android.content.Context;import com.journaldev.mvpdagger2retroiftrxjava.MainActivity;
import com.journaldev.mvpdagger2retroiftrxjava.di.module.AdapterModule;
import com.journaldev.mvpdagger2retroiftrxjava.di.module.MainActivityMvpModule;
import com.journaldev.mvpdagger2retroiftrxjava.di.qualifier.ActivityContext;
import com.journaldev.mvpdagger2retroiftrxjava.di.scopes.ActivityScope;
import dagger.Component;@ActivityScope
@Component(modules = {AdapterModule.class, MainActivityMvpModule.class}, dependencies = ApplicationComponent.class)
public interface MainActivityComponent {@ActivityContextContext getContext();void injectMainActivity(MainActivity mainActivity);
}

PresenterImpl.java

PresenterImpl.java

package com.journaldev.mvpdagger2retroiftrxjava.mvp;import com.journaldev.mvpdagger2retroiftrxjava.pojo.CryptoData;
import com.journaldev.mvpdagger2retroiftrxjava.retrofit.APIInterface;
import java.util.List;
import javax.inject.Inject;
import rx.Observer;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;public class PresenterImpl implements MainActivityContract.Presenter {APIInterface apiInterface;MainActivityContract.View mView;@Injectpublic PresenterImpl(APIInterface apiInterface, MainActivityContract.View mView) {this.apiInterface = apiInterface;this.mView = mView;}@Overridepublic void loadData() {mView.showProgress();apiInterface.getData("10").subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<List<CryptoData>>() {@Overridepublic void onCompleted() {mView.showComplete();mView.hideProgress();}@Overridepublic void onError(Throwable e) {mView.showError("Error occurred");mView.hideProgress();}@Overridepublic void onNext(List<CryptoData> data) {mView.showData(data);}});}
}

@Inject on the constructor says that this class’s object would be injected in the MainActivity.
The Presenter invokes the required View interface’s methods that’ll trigger the actions in the MainActivity.

构造函数上的@Inject表示此类的对象将被注入MainActivity中。
Presenter调用所需的View接口的方法,这些方法将触发MainActivity中的操作。

MyApplication.java

MyApplication.java

package com.journaldev.mvpdagger2retroiftrxjava;import android.app.Activity;
import android.app.Application;import com.journaldev.mvpdagger2retroiftrxjava.di.component.ApplicationComponent;
import com.journaldev.mvpdagger2retroiftrxjava.di.component.DaggerApplicationComponent;
import com.journaldev.mvpdagger2retroiftrxjava.di.module.ContextModule;public class MyApplication extends Application {ApplicationComponent applicationComponent;@Overridepublic void onCreate() {super.onCreate();applicationComponent = DaggerApplicationComponent.builder().contextModule(new ContextModule(this)).build();applicationComponent.injectApplication(this);}public static MyApplication get(Activity activity){return (MyApplication) activity.getApplication();}public ApplicationComponent getApplicationComponent() {return applicationComponent;}
}

MainActivity.java

MainActivity.java

package com.journaldev.mvpdagger2retroiftrxjava;import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;import com.journaldev.mvpdagger2retroiftrxjava.di.component.ApplicationComponent;
import com.journaldev.mvpdagger2retroiftrxjava.di.component.DaggerMainActivityComponent;
import com.journaldev.mvpdagger2retroiftrxjava.di.component.MainActivityComponent;
import com.journaldev.mvpdagger2retroiftrxjava.di.module.MainActivityContextModule;
import com.journaldev.mvpdagger2retroiftrxjava.di.module.MainActivityMvpModule;
import com.journaldev.mvpdagger2retroiftrxjava.di.qualifier.ActivityContext;
import com.journaldev.mvpdagger2retroiftrxjava.di.qualifier.ApplicationContext;
import com.journaldev.mvpdagger2retroiftrxjava.mvp.MainActivityContract;
import com.journaldev.mvpdagger2retroiftrxjava.mvp.PresenterImpl;
import com.journaldev.mvpdagger2retroiftrxjava.pojo.CryptoData;import java.util.List;import javax.inject.Inject;public class MainActivity extends AppCompatActivity implements MainActivityContract.View, RecyclerViewAdapter.ClickListener {private RecyclerView recyclerView;private ProgressBar progressBar;MainActivityComponent mainActivityComponent;@Injectpublic RecyclerViewAdapter recyclerViewAdapter;@Inject@ApplicationContextpublic Context mContext;@Inject@ActivityContextpublic Context activityContext;@InjectPresenterImpl presenter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ApplicationComponent applicationComponent = MyApplication.get(this).getApplicationComponent();mainActivityComponent = DaggerMainActivityComponent.builder().mainActivityContextModule(new MainActivityContextModule(this)).mainActivityMvpModule(new MainActivityMvpModule(this)).applicationComponent(applicationComponent).build();mainActivityComponent.injectMainActivity(this);recyclerView = findViewById(R.id.recyclerView);recyclerView.setLayoutManager(new LinearLayoutManager(activityContext));recyclerView.setAdapter(recyclerViewAdapter);progressBar = findViewById(R.id.progressBar);presenter.loadData();}@Overridepublic void launchIntent(String name) {Toast.makeText(mContext, name, Toast.LENGTH_SHORT).show();// startActivity(new Intent(activityContext, DetailActivity.class).putExtra("name", name));}@Overridepublic void showData(List<CryptoData> data) {recyclerViewAdapter.setData(data);}@Overridepublic void showError(String message) {Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();}@Overridepublic void showComplete() {}@Overridepublic void showProgress() {progressBar.setVisibility(View.VISIBLE);}@Overridepublic void hideProgress() {progressBar.setVisibility(View.GONE);}
}

Thanks to DI and MVP, we’ve injected everything and separated the network calls from the MainActivity.
The MainActivity.java only populates the views as per the instructions from the Presenter.

感谢DI和MVP,我们注入了所有内容,并将网络调用与MainActivity分开。
MainActivity.java仅按照Presenter中的说明填充视图。

The code for the RecyclerViewAdapter.java class is given below:

下面给出了RecyclerViewAdapter.java类的代码:

package com.journaldev.mvpdagger2retroiftrxjava;import android.support.constraint.ConstraintLayout;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.journaldev.mvpdagger2retroiftrxjava.pojo.CryptoData;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {private List<CryptoData> data;private RecyclerViewAdapter.ClickListener clickListener;@Injectpublic RecyclerViewAdapter(ClickListener clickListener) {this.clickListener = clickListener;data = new ArrayList<>();}@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_view_list_row, parent, false));}@Overridepublic void onBindViewHolder(ViewHolder holder, int position) {holder.txtCoin.setText(data.get(position).symbol);holder.txtCurrentPrice.setText(data.get(position).priceUsd);holder.txt1HourChange.setText(data.get(position).percentChange1h + "%");holder.txt24HourChange.setText(data.get(position).percentChange24h + "%");holder.txt7DayChange.setText(data.get(position).percentChange7d + "%");}@Overridepublic int getItemCount() {return data.size();}class ViewHolder extends RecyclerView.ViewHolder {private TextView txtCoin;private TextView txtCurrentPrice;private TextView txt1HourChange;private TextView txt24HourChange;private TextView txt7DayChange;private ConstraintLayout constraintLayoutContainer;ViewHolder(View itemView) {super(itemView);txtCoin = itemView.findViewById(R.id.txtCoin);txtCurrentPrice = itemView.findViewById(R.id.txtCurrentPrice);txt1HourChange = itemView.findViewById(R.id.txtOneHourChange);txt24HourChange = itemView.findViewById(R.id.txt24HourChange);txt7DayChange = itemView.findViewById(R.id.txt7DayChange);constraintLayoutContainer = itemView.findViewById(R.id.constraintLayout);constraintLayoutContainer.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {clickListener.launchIntent(data.get(getAdapterPosition()).name);}});}}public interface ClickListener {void launchIntent(String name);}public void setData(List<CryptoData> data) {this.data.addAll(data);notifyDataSetChanged();}
}

REBUILD the Project to create the Dagger files automatically.

重建项目以自动创建Dagger文件。

The output of the above application in action is given below:

上面应用程序的输出如下:

This brings an end to this hands-on tutorial in which we’ve used MVP, Dagger2, Retrofit, RxJava along with a RecyclerView. You can download the project from the link below.

这结束了本动手教程,在该教程中,我们将MVP,Dagger2,Retrofit,RxJava和RecyclerView一起使用。 您可以从下面的链接下载项目。

MVPDagger2RetroiftRxJavaMVPDagger2RetroiftRxJava

翻译自: https://www.journaldev.com/20654/android-mvp-dagger2-retrofit-rxjava

mvp+dagger2

mvp+dagger2_Android MVP + Dagger2 +改造+ RxJava相关推荐

  1. 模仿开眼的视频APP,基于MVP+rxjava2+Retrofit+Dagger2+Glide+Realm+GSYVideoPlayer

    EyesOpener EyesOpener,一款开眼高仿APP, 基于 MVP+rxjava2+Retrofit+![Dagger2](https://img-blog.csdn.net/201806 ...

  2. 风云获微软2010年MVP和MVP奖杯与奖牌

    今天早上收到美国微软寄来的MVP奖杯与奖牌以及合同和大家分享一下. 微软MVP奖牌 微软MVP奖杯 MVP包裹 转载于:https://www.cnblogs.com/slteam/archive/2 ...

  3. 奖项-MVP:MVP(微软最有价值专家)百科

    ylbtech-奖项-MVP:MVP(微软最有价值专家)百科 微软最有价值专家(MVP) 是指具备一种或多种微软技术专业知识,并且积极参与在线或离线的社群活动,经常与其他专业人士分享知识和专业技能,受 ...

  4. 转吴小龙的 mvp Android MVP 实例

    转吴小龙的 mvp Android MVP 实例 详情点此http://wuxiaolong.me/2015/09/23/AndroidMVPSample/

  5. Android MVP开发模式及Retrofit + RxJava封装

    代码已上传到Github,因为接口都是模拟无法进行测试,明白大概的逻辑就行了! 欢迎浏览我的博客--https://pushy.site 1. MVP模式 1.1 介绍 如果熟悉MVP模式架构的话,对 ...

  6. android flux 与mvp,使用 MVP 时在设计上的考量

    在"FluxJava: 给 Java 使用的 Flux 库"这篇文章中提到,设计中使用 MVP 最大的问题,是会让不同的画面形成一组.一组的 Class,但各组之间是独立的.MVP ...

  7. MVP Story——MVP苏鹏的10年技术生涯

    MVP苏鹏的10年技术生涯 苏鹏ASP.NET 方向MVP , 他在接触微软开发技术大概是10年前的时候,那时候他刚刚上大学,互联网热潮还没有退潮,asp作为时髦的技术方兴未艾,像每个怀揣梦想的技术人 ...

  8. [转载]MVP(SC),MVP(PV),PM,MVVM 和 MVC 表现模式架构对比

    原文链接:http://tech.ddvip.com/2010-03/1269414998148153.html(为自己方便,也为大家方便!) 翻译 CodeProject 上的一篇文章,对常见的几种 ...

  9. 吴小龙的 mvp Android MVP 实例

    http://wuxiaolong.me/2015/09/23/AndroidMVPSample/ https://github.com/WuXiaolong/AndroidMVPSample

最新文章

  1. canvas刮奖效果
  2. LNMP和LAMP的编译安装
  3. 很久没有回到我51的家啦!
  4. Android 10.0 系统启动之SystemServer进程-[Android取经之路]
  5. python 三步问题
  6. 头发一周洗几次才适宜? - 生活至上,美容至尚!
  7. 阿里云边缘云ENS再升级,四大场景应用加速产业数字化落地
  8. springboot配置连接rds_java – 在AWS-EC2上运行的SpringBoot应用程序无法连接到MySQL AWS-RDS数据库...
  9. P1975 [国家集训队]排队(三维偏序)
  10. 使用Apriori进行关联分析(一)
  11. .netcore mysql_.netcore基于mysql的codefirst
  12. 有问有答 | 你真的理解微服务架构吗?
  13. 云计算时代下的数据中心运维之路
  14. TThread类详解转
  15. 【原】unity3D之Draw Call
  16. qt清空qtablew_qt项目:员工信息管理系统
  17. python和scre_python中变量命名的基本规则,标识符和关键字
  18. 数据分析入门——Matplotlib数据可视化
  19. 项目管理工具---用Excel制作甘特图
  20. python 中的 __repr__() 方法

热门文章

  1. Xorg可以使用hot-plug了,不过配置很麻烦
  2. 软核、固核、硬核的区别
  3. HTML5网页录音和上传到服务器,支持PC、Android,支持IOS微信
  4. java中equals,hashcode和==的区别
  5. sqlite3 语法
  6. os.path 大全
  7. 路漫漫其修远兮,吾要上下左右前后而求索
  8. [轉]最流行的PHP MVC框架
  9. Global GUI map for automation with VS.NET
  10. Failed to meta-introspect annotation interface org.springframework.web.bind.annotation.RequestBody: