Retrofit2 + RxAndroidで通信してみる


### 為替APIを使ってRetrofit2+RxAndroidで通信を試してみたいと思います。
内容としてはUSDからJPYに変換したレートを受け取りTextViewに表示するだけです。
使うAPI: http://fixer.io/ なかなか便利そうですね。

今回の実際のリクエストです。http://api.fixer.io/latest?base=USD&symbols=JPY
下記のように1件JPYのレートが入っています。

```Json:今回の例
{
	base: "USD",
	date: "2016-11-01",
	rates: {
	JPY: 104.83
	}
}
```

まずはappのbuild.gradleの設定から

```gradle:build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'

    // 追加
    compile 'io.reactivex:rxjava:1.1.0'
    compile 'io.reactivex:rxandroid:1.1.0'
    compile 'com.google.code.gson:gson:2.6.2'
    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'
}

```

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

```xml: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" />
    
    <application
        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の作成
rxじゃないObservableをimportしないように注意

```java:ExchangeRateApi.java

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

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

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

```java: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;
    }
}
```

```java:CountryCode.java

public class CountryCode {
    private float JPY;

    public float getJPY() {
        return JPY;
    }
}
```

MainActivityのxmlにTextViewを1つ追加

```xml: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から使ってみる

```java:MainActivity.java
		
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Retrofit retrofit = new Retrofit.Builder()
                // エンドポイントの設定
                .baseUrl("http://api.fixer.io")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

        retrofit.create(ExchangeRateApi.class)
                // USドルからJPYに絞り込むクエリ
                .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 午後5.10.02.png](https://qiita-image-store.s3.amazonaws.com/0/33553/608a79e7-b9c5-94d0-4fd9-3c62f693b137.png "スクリーンショット 2016-11-14 午後5.10.02.png")

### もう少し便利にしてみる
先ほどのbuild.gradleに2行追加

```gradle:build.gradle

dependencies {

    // 追加
    compile 'io.reactivex:rxjava:1.1.0'
    compile 'io.reactivex:rxandroid:1.1.0'
    compile 'com.google.code.gson:gson:2.6.2'
    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'
    
    // さらに追加
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
}

```
Okhttpクライアントを作成し、追加。
今回はログを追加してみる。
他にもヘッダーの設定等、色々追加できる。

```java:MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
		
		 // okhttpクライアントを作成
        OkHttpClient okHttpclient = new OkHttpClient.Builder()
        		  // ヘッダーを追加できるようにする
                .addInterceptor(new RequestHeaderInterceptor())
                // ログを出す
                .addInterceptor(loggingInterceptor)
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                // エンドポイントの設定
                .baseUrl("http://api.fixer.io")
                // okhttpクライアントを追加
                .client(okHttpclient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

        retrofit.create(ExchangeRateApi.class)
                // USドルからJPYに絞り込むクエリ
                .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()));
                    }
                });
    }
	
	// ヘッダーのクラス
    public class RequestHeaderInterceptor implements Interceptor {

        @Override
        public okhttp3.Response intercept(Chain chain) throws IOException {
            final Request.Builder builder = chain.request().newBuilder();
            builder.addHeader("HEADER", "VALUE");
            return chain.proceed(builder.build());
        }
    }
}
```




以上で終わりですが、さらににDagger2を加えたのも追記しておきます。

Dagger2 + Retrofit2 + RxAndroidで通信してみる
http://qiita.com/MuuKojima/items/8088b43876dc8d3d1745
Dagger2導入
http://qiita.com/MuuKojima/items/51cd6c1e59479cdcc2f4