mvp+dagger2_Android MVP + Dagger2 +改造+ RxJava

mvp+dagger2

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

在本教程中,我们将使用MVPDagger2RetrofitRxJava开发应用程序。

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库的概述。
我们已经单独介绍了它们,并结合了以下指定的教程链接:

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.

android mvp dagger2 retrofit rxjava libraries

在您应用的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.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <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>

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">

    <TextView
        android:id="@+id/txtCoin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/txtCurrentPrice"
        app:layout_constraintTop_toTopOf="parent"
         />

    <TextView
        android:id="@+id/txtCurrentPrice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/txtCoin"
        />


    <TextView
        android:id="@+id/txtOneHourChange"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent" />

    <TextView
        android: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" />


    <TextView
        android:id="@+id/txt24HourChange"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/txtOneHourChange" />

    <TextView
        android: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" />


    <TextView
        android: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" />

    <TextView
        android: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
    @ApplicationContext
    public 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
    @ActivityScope
    public MainActivity providesMainActivity() {
        return mainActivity;
    }

    @Provides
    @ActivityScope
    @ActivityContext
    public 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
    @ApplicationScope
    APIInterface getApiInterface(Retrofit retroFit) {
        return retroFit.create(APIInterface.class);
    }

    @Provides
    @ApplicationScope
    Retrofit getRetrofit(OkHttpClient okHttpClient) {
        return new Retrofit.Builder()
                .baseUrl("https://api.coinmarketcap.com/v1/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .client(okHttpClient)
                .build();
    }

    @Provides
    @ApplicationScope
    OkHttpClient getOkHttpCleint(HttpLoggingInterceptor httpLoggingInterceptor) {
        return new OkHttpClient.Builder()
                .addInterceptor(httpLoggingInterceptor)
                .build();
    }

    @Provides
    @ApplicationScope
    HttpLoggingInterceptor 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
    @ActivityScope
    MainActivityContract.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
    @ActivityScope
    public RecyclerViewAdapter getCoinList(RecyclerViewAdapter.ClickListener clickListener) {
        return new RecyclerViewAdapter(clickListener);
    }

    @Provides
    @ActivityScope
    public 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();

    @ApplicationContext
    Context 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 {

    @ActivityContext
    Context 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;

    @Inject
    public PresenterImpl(APIInterface apiInterface, MainActivityContract.View mView) {
        this.apiInterface = apiInterface;
        this.mView = mView;
    }

    @Override
    public void loadData() {

        mView.showProgress();

        apiInterface.getData("10").subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<List<CryptoData>>() {
                    @Override
                    public void onCompleted() {
                        mView.showComplete();
                        mView.hideProgress();
                    }

                    @Override
                    public void onError(Throwable e) {
                        mView.showError("Error occurred");
                        mView.hideProgress();
                    }

                    @Override
                    public 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;

    @Override
    public 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;

    @Inject
    public RecyclerViewAdapter recyclerViewAdapter;

    @Inject
    @ApplicationContext
    public Context mContext;

    @Inject
    @ActivityContext
    public Context activityContext;

    @Inject
    PresenterImpl presenter;


    @Override
    protected 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();


    }

    @Override
    public void launchIntent(String name) {
        Toast.makeText(mContext, name, Toast.LENGTH_SHORT).show();
        // startActivity(new Intent(activityContext, DetailActivity.class).putExtra("name", name));
    }

    @Override
    public void showData(List<CryptoData> data) {
        recyclerViewAdapter.setData(data);
    }

    @Override
    public void showError(String message) {
        Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showComplete() {

    }

    @Override
    public void showProgress() {
        progressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public 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;

    @Inject
    public RecyclerViewAdapter(ClickListener clickListener) {
        this.clickListener = clickListener;
        data = new ArrayList<>();
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_view_list_row, parent, false));
    }

    @Override
    public 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 + "%");

    }

    @Override
    public 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() {
                @Override
                public 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:

android-mvp-dagger2-retrofit-rxjava

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

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一起使用。 您可以从下面的链接下载项目。

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

mvp+dagger2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值