Edited at

Dagger2 + Retrofit2 + RxAndroidで通信してみる

More than 1 year has passed since last update.


為替APIを使ってDagger2 + Retrofit2 + RxAndroidで通信を試してみたいと思います。

基本的には、以前書いたものにDagger2を加えただけになります。

http://qiita.com/MuuKojima/items/01a0738e4c4d1879189c

今回の内容としてはUSDからJPYに変換した為替レートを受け取りTextViewに表示するだけです。

使うAPI: http://fixer.io/ なかなか便利そうですね。

実際のリクエストです。http://api.fixer.io/latest?base=USD&symbols=JPY

下記のように1件JPYのレートが入っています。


今回の例

{

base: "USD",
date: "2016-11-09",
rates: {
JPY: 103.92
}
}

それでは、まずrootのbuild.gradleの設定から


build.gradle

buildscript {

repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'

// 追加
classpath 'com.uphyca.gradle:gradle-android-apt-plugin:0.9.4'
}
}


appのbuild.gradle


build.gradle

apply plugin: 'com.android.application'

// 追加 ↑の下に入れる事
apply plugin: 'android-apt'

dependencies {

//////// 追加 ////////

// RxAndroid
compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'
// Dagger
compile 'com.google.dagger:dagger:2.2'
apt 'com.google.dagger:dagger-compiler:2.2'
// Retrofit
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
// OkHttp
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
// Gson
compile 'com.google.code.gson:gson:2.6.2'
}


AndroidManifest.xmlにインターネットパーミッションを1行追加


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="kojimation.com.retrofitsample">

<!-- 追加 -->
<uses-permission android:name="android.permission.INTERNET" />

</manifest>


今回使う、為替レートを取得するAPIの作成

rxじゃないObservableをimportしないように注意


ExchangeRateApi.java


public interface ExchangeRateApi {
String URL = "/latest";

@GET(URL)
Observable<ExchangeRateResponse> getExchangeRate(@Query("base") String base,
@Query("symbols") String symbols);
}


AppModuleを作成


AppModule.java

@Module

public class AppModule {

Application mApplication;

public AppModule(Application mApplication) {
this.mApplication = mApplication;
}

@Provides
@Singleton
Application provideApplication() {
return mApplication;
}
}


ApiModuleを作成


ApiModule.java


@Module
public class ApiModule {

@Provides
@Singleton
Gson provideGson() {
GsonBuilder gsonBuilder = new GsonBuilder();
return gsonBuilder.create();
}

@Provides
@Singleton
OkHttpClient provideOkhttpClient() {
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
return client.build();
}

@Provides
@Singleton
Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
// ベースのURLの設定
.baseUrl("http://api.fixer.io")
.client(okHttpClient)
.build();
}

@Provides
@Singleton
public ExchangeRateApi providesExchangeApi(Retrofit retrofit) {
return retrofit.create(ExchangeRateApi.class);
}
}


AppComponentを作成


AppComponent.java

@Singleton

@Component(modules = {AppModule.class, ApiModule.class})
public interface AppComponent {
void inject(MainActivity activity);
}

一旦、実行もしくはrebuildする(DaggerAppComponentが生成される)

Applicationクラスを継承したAppApplicationを作成


Application.java

public class AppApplication extends Application {

private AppComponent mAppComponent;

@Override
public void onCreate() {
super.onCreate();

mAppComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.apiModule(new ApiModule())
.build();
}

public AppComponent getAppComponent() {
return mAppComponent;
}
}


Applicationクラスを使うので、AndroidManifest.xmlに android:name=".AppApplication" を一行追記


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="kojimation.com.daggerretrofitrxandorid">

<!-- 追加 -->
<uses-permission android:name="android.permission.INTERNET" />

<!-- このタグの中に追加 -->
<application
android:name=".AppApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
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>


APIから返って来るレスポンスのオブジェクトを作成


ExchangeRateResponse.java


public class ExchangeRateResponse {
private String base;
private String date;
private CountryCode rates;

public String getBase() {
return base;
}

public String getDate() {
return date;
}

public CountryCode getRates() {
return rates;
}
}



CountryCode.java


public class CountryCode {
private float JPY;

public float getJPY() {
return JPY;
}
}


MainActivityのxmlにTextViewを1つ追加


activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="kojimation.com.retrofitsample.MainActivity">

<!-- 追加 -->
<TextView
android:id="@+id/txt_jpy"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>


MainActivityから実際に使ってみる


MainActivity.java

public class MainActivity extends AppCompatActivity {

@Inject
ExchangeRateApi mExchangeRateApi;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((AppApplication) getApplication()).getAppComponent().inject(this);

mExchangeRateApi.getExchangeRate("USD", "JPY")
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ExchangeRateResponse>() {
@Override
public void onCompleted() {

}

@Override
public void onError(Throwable e) {
Log.d("通信 -> ", "失敗" + e.toString());
}

@Override
public void onNext(ExchangeRateResponse exchangeRateResponse) {
Log.d("通信 -> ", "成功");
TextView textView = (TextView) findViewById(R.id.txt_jpy);
textView.setText("JPY: " + String.valueOf(exchangeRateResponse.getRates().getJPY()));
}
});
}
}


実行結果

スクリーンショット 2016-11-14 午後4.51.49.png

Githubにサンプルを置いておきます

https://github.com/MuuKojima/DaggerRetrofitRxAndroidSample

MVPの構成を適用したものを追記しておきます

http://qiita.com/MuuKojima/items/8843c9451339a8b68f22