2015.11.27
オープンソースライブラリ研究会
Android編
Shun Nakahara
自己紹介
✤ Shun Nakahara
✤ 27
✤ iOS/Android
✤ iOS 大好きです!
✤ @shun_nakahara
全員エンジニア合コンをやってみた
人生初の合コン
FiNC 紹介
一生に一度のかけがえのない人生の成功をサポートする
iOS 大好きです!!
iOS で発表したかったんですが…
RxJava + Retrofit
RxJava + Retrofit
✤ RxJava を簡単に紹介
✤ Retrofit を簡単に紹介
✤ 二つを合わせたテクニックを紹介
RxJava
RxJava
✤ Reactive Extensions Java
✤ リアクティブプログラミングをするためのライブラリ
✤ 同期処理、非同期処理、遅延実行…
RxJava
✤ 基本的な使い方
✤ 非同期処理
✤ 同期処理
✤ RxAndroid
Gradle の準備
// RxJava

compile 'io.reactivex:rxjava:1.0.15'
基本的な書き方
String name = “shun";


Subscription subscription = Observable.from(new String[]{name}).subscribe(new Action1<String>() {

@Override

public void call(String string) {

String name = "nakahara " + string;

System.out.print(name);

}

});


subscription.unsubscribe();
基本的な処理を便利に!?
Observable.OnSubscribe<String> onSubscribe = new Observable.OnSubscribe<String>() {

@Override

public void call(Subscriber<? super String> subscriber) {

final String name = "shun"; // 重い処理などをここで行う。

String fullName = "nakahara " + name;



subscriber.onNext(fullName);

subscriber.onCompleted();

}

};


Subscription subscription = Observable.create(onSubscribe).subscribe(new Action1<String>() {

@Override

public void call(String string) {

System.out.print(string);

}

});


subscription.unsubscribe();
非同期処理
Observable.OnSubscribe<String> onSubscribe = new Observable.OnSubscribe<String>() {

@Override

public void call(Subscriber<? super String> subscriber) {



// 通信処理



boolean isSuccess = false;

String response = "response";

if (isSuccess) {

subscriber.onNext(response);

subscriber.onCompleted();

} else {

subscriber.onError(new NetworkErrorException("connect error"));

}

}

};

Observable<String> stringObservable = Observable.create(onSubscribe);

stringObservable.subscribe(new Observer<String>() {

@Override

public void onCompleted() {

// network completed

}



@Override

public void onError(Throwable e) {

// network error message

}



@Override

public void onNext(String string) {

// network success response

}

});
同期処理を書きたい時
Observable.OnSubscribe<String> onSubscribe = new Observable.OnSubscribe<String>() {

@Override

public void call(Subscriber<? super String> subscriber) {



// 通信処理



boolean isSuccess = false;

String response = "response";

if (isSuccess) {

subscriber.onNext(response);

subscriber.onCompleted();

} else {

subscriber.onError(new NetworkErrorException("connect error"));

}

}

};



Observable<String> stringObservable = Observable.create(onSubscribe);



String response = stringObservable.toBlocking().single();

if (response == null) {

// error

} else {

// success

}
気づいた人いますか?
メソッドに切す
public Observable<String> request() {

Observable.OnSubscribe<String> onSubscribe = new Observable.OnSubscribe<String>() {

@Override

public void call(Subscriber<? super String> subscriber) {



// 通信処理



boolean isSuccess = false;

String response = "response";

if (isSuccess) {

subscriber.onNext(response);

subscriber.onCompleted();

} else {

subscriber.onError(new NetworkErrorException("connect error"));

}

}

};

return Observable.create(onSubscribe);

}
非同期処理
request().subscribe(new Observer<String>() {

@Override

public void onCompleted() {

// network completed

}



@Override

public void onError(Throwable e) {

// network error

}



@Override

public void onNext(String s) {

// response call back

}

});
同期処理
String response = request().toBlocking().single();

if (response == null) {

// network error

} else {

// response call back

}
なんだかこれだと使えそうな
気がしますね!d( ̄  ̄)
RxAndroid
✤ Reactive Extensions Android
✤ リアクティブプログラミングをするためのライブラリ
✤ 同期処理、非同期処理、遅延実行…
✤ RxJavaを内包しAndroidで利用するための機能を追加
✤ Android Handler / Thread 処理
RxAndroid…他にも
✤ RxLifecycle
✤ RxBinding
✤ SqlBrite
✤ Android-ReactiveLocation
✤ rx-preferences
RxAndroid
✤ AndroidSchedulers
✤ HandlerSchedulers
Gradle の準備
// RxJava

compile 'io.reactivex:rxjava:1.0.15'



// RXAndroid

compile 'io.reactivex:rxandroid:1.0.1'
Android Schedulers
request().subscribeOn(Schedulers.newThread())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new Observer<String>() {

@Override

public void onCompleted() {

// network completed
// main thread

}



@Override

public void onError(Throwable e) {

// network error

// main thread

}



@Override

public void onNext(String s) {

// response call back

// main thread

}

});
Handler Schedulers
Handler handler = new Handler();

request().subscribeOn(Schedulers.newThread())

.observeOn(HandlerScheduler.from(handler))

.subscribe(new Observer<String>() {

@Override

public void onCompleted() {

// network completed

// handler thread

}



@Override

public void onError(Throwable e) {

// network error

// handler thread

}



@Override

public void onNext(String s) {

// response call back

// handler thread

}

});
RxJava わかってきたところで
Retrofit
Retrofit
✤ A Type safe HTTP client for Android and Java
✤ Android の為の REST 通信を手軽に実装できる!?
✤ Retrofit 2.0.0-bata2 を利用します。
Retrofit
✤ 基本的な使い方
✤ 非同期処理
✤ 同期処理
✤ RxJava を組み込んでみる
Gradle の準備
// Retrofit

compile ‘com.squareup.retrofit:retrofit:2.0.0-beta2'
// gson

compile ‘com.google.code.gson:gson:2.4'
// Converter Gson

compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'

Proguard の準備
# Retrofit Proguard

-dontwarn retrofit.**

-keep class retrofit.** { *; }

-keepattributes Signature

-keepattributes Exceptions
基本的な使い方
Model Class の作成
public class SignIn {

@SerializedName("access_token")

public final String accessToken;



@SerializedName("user_id")

public final int userId;



@SerializedName("group_id")

public final int group_id;



public SignIn(String accessToken, int userId, int group_id) {

this.accessToken = accessToken;

this.userId = userId;

this.group_id = group_id;

}

}
Service Interface 作成
public interface UsersService {

@FormUrlEncoded

@POST("/v3/users/sign_in")

Call<SignIn> signIn(@Field("email") String email, @Field("password") String password);

}
Service Interface 作成
public interface UsersService {

@FormUrlEncoded

@POST("/v3/users/sign_in")

Call<SignIn> signIn(@Field("email") String email, @Field("password") String password);

}
非同期処理
// Gson Converter Factory

GsonConverterFactory factory = GsonConverterFactory.create(new Gson());



// Retrofit

Retrofit retrofit = new Retrofit.Builder()

.baseUrl(baseUrl)

.addConverterFactory(factory)

.build();



// Users Service

UsersService usersService = retrofit.create(UsersService.class);



// Call

Call<SignIn> call = usersService.signIn(Email, Password);

call.enqueue(new Callback<SignIn>() {

@Override

public void onResponse(Response<SignIn> response, Retrofit retrofit) {

// network success

}



@Override

public void onFailure(Throwable t) {

// network error

}

});
同期処理
// Gson Converter Factory

GsonConverterFactory factory = GsonConverterFactory.create(new Gson());



// Retrofit

Retrofit retrofit = new Retrofit.Builder()

.baseUrl(baseUrl)

.addConverterFactory(factory)

.build();



// Users Service

UsersService usersService = retrofit.create(UsersService.class);



// Call

Call<SignIn> call = usersService.signIn(Email, Password);

try {

Response<SignIn> response = call.execute();

} catch (IOException e) {

e.printStackTrace();

}
・・・
クラッシュ
RxJava + Retrofit
Service Interface(RxJava版)
public interface UsersService {

@FormUrlEncoded

@POST("/v3/users/sign_in")

Observable<SignIn> signIn(@Field("email") String email, @Field("password") String password);

}

非同期処理(RxJava版)
// Gson Converter Factory

GsonConverterFactory factory = GsonConverterFactory.create(new Gson());



// RxJava Call Adapter

RxJavaCallAdapterFactory adapterFactory = RxJavaCallAdapterFactory.create();



// Retrofit

Retrofit retrofit = new Retrofit.Builder()

.baseUrl(baseUrl)

.addConverterFactory(factory)

.addCallAdapterFactory(adapterFactory)

.build();



// Users Service

UsersService usersService = retrofit.create(UsersService.class);



// User Service

Observable<SignIn> observable = usersService.signIn(Email, Password);

observable.subscribeOn(Schedulers.newThread())

.observeOn(AndroidSchedulers.mainThread())

.subscribe(new Observer<SignIn>() {

@Override

public void onCompleted() {

// network completed

}



@Override

public void onError(Throwable e) {

// network error

}



@Override

public void onNext(SignIn signIn) {

// network success

}

});
同期処理(RxJava版)
// Gson Converter Factory

GsonConverterFactory factory = GsonConverterFactory.create(new Gson());



// RxJava Call Adapter

RxJavaCallAdapterFactory adapterFactory = RxJavaCallAdapterFactory.create();



// Retrofit

Retrofit retrofit = new Retrofit.Builder()

.baseUrl(baseUrl)

.addConverterFactory(factory)

.addCallAdapterFactory(adapterFactory)

.build();



// Users Service

UsersService usersService = retrofit.create(UsersService.class);



// Call

Observable<SignIn> observable = usersService.signIn(Email, Password);

SignIn signIn = observable

.subscribeOn(Schedulers.newThread())

.toBlocking()

.single();



if (signIn == null) {

// network error

} else {

// network success

}
Retrofit でハマったこと
Retrofit でハマったこと
✤ Twitter Kit では Retrofit 1.8 を使っている
✤ Retrofit 1.8-1.9 と Retrofit 2.0 で設定の変更
✤ Retrofit 2.0 では、RxJava の Call Adapter が必要
ありがとうございました。

Rx java x retrofit

  • 1.
  • 2.
    自己紹介 ✤ Shun Nakahara ✤27 ✤ iOS/Android ✤ iOS 大好きです! ✤ @shun_nakahara
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
    RxJava + Retrofit ✤RxJava を簡単に紹介 ✤ Retrofit を簡単に紹介 ✤ 二つを合わせたテクニックを紹介
  • 10.
  • 11.
    RxJava ✤ Reactive ExtensionsJava ✤ リアクティブプログラミングをするためのライブラリ ✤ 同期処理、非同期処理、遅延実行…
  • 12.
  • 13.
    Gradle の準備 // RxJava
 compile'io.reactivex:rxjava:1.0.15'
  • 14.
    基本的な書き方 String name =“shun"; 
 Subscription subscription = Observable.from(new String[]{name}).subscribe(new Action1<String>() {
 @Override
 public void call(String string) {
 String name = "nakahara " + string;
 System.out.print(name);
 }
 }); 
 subscription.unsubscribe();
  • 15.
    基本的な処理を便利に!? Observable.OnSubscribe<String> onSubscribe =new Observable.OnSubscribe<String>() {
 @Override
 public void call(Subscriber<? super String> subscriber) {
 final String name = "shun"; // 重い処理などをここで行う。
 String fullName = "nakahara " + name;
 
 subscriber.onNext(fullName);
 subscriber.onCompleted();
 }
 }; 
 Subscription subscription = Observable.create(onSubscribe).subscribe(new Action1<String>() {
 @Override
 public void call(String string) {
 System.out.print(string);
 }
 }); 
 subscription.unsubscribe();
  • 16.
    非同期処理 Observable.OnSubscribe<String> onSubscribe =new Observable.OnSubscribe<String>() {
 @Override
 public void call(Subscriber<? super String> subscriber) {
 
 // 通信処理
 
 boolean isSuccess = false;
 String response = "response";
 if (isSuccess) {
 subscriber.onNext(response);
 subscriber.onCompleted();
 } else {
 subscriber.onError(new NetworkErrorException("connect error"));
 }
 }
 };
 Observable<String> stringObservable = Observable.create(onSubscribe);
 stringObservable.subscribe(new Observer<String>() {
 @Override
 public void onCompleted() {
 // network completed
 }
 
 @Override
 public void onError(Throwable e) {
 // network error message
 }
 
 @Override
 public void onNext(String string) {
 // network success response
 }
 });
  • 17.
    同期処理を書きたい時 Observable.OnSubscribe<String> onSubscribe =new Observable.OnSubscribe<String>() {
 @Override
 public void call(Subscriber<? super String> subscriber) {
 
 // 通信処理
 
 boolean isSuccess = false;
 String response = "response";
 if (isSuccess) {
 subscriber.onNext(response);
 subscriber.onCompleted();
 } else {
 subscriber.onError(new NetworkErrorException("connect error"));
 }
 }
 };
 
 Observable<String> stringObservable = Observable.create(onSubscribe);
 
 String response = stringObservable.toBlocking().single();
 if (response == null) {
 // error
 } else {
 // success
 }
  • 18.
  • 19.
    メソッドに切す public Observable<String> request(){
 Observable.OnSubscribe<String> onSubscribe = new Observable.OnSubscribe<String>() {
 @Override
 public void call(Subscriber<? super String> subscriber) {
 
 // 通信処理
 
 boolean isSuccess = false;
 String response = "response";
 if (isSuccess) {
 subscriber.onNext(response);
 subscriber.onCompleted();
 } else {
 subscriber.onError(new NetworkErrorException("connect error"));
 }
 }
 };
 return Observable.create(onSubscribe);
 }
  • 20.
    非同期処理 request().subscribe(new Observer<String>() {
 @Override
 publicvoid onCompleted() {
 // network completed
 }
 
 @Override
 public void onError(Throwable e) {
 // network error
 }
 
 @Override
 public void onNext(String s) {
 // response call back
 }
 });
  • 21.
    同期処理 String response =request().toBlocking().single();
 if (response == null) {
 // network error
 } else {
 // response call back
 }
  • 22.
  • 23.
    RxAndroid ✤ Reactive ExtensionsAndroid ✤ リアクティブプログラミングをするためのライブラリ ✤ 同期処理、非同期処理、遅延実行… ✤ RxJavaを内包しAndroidで利用するための機能を追加 ✤ Android Handler / Thread 処理
  • 24.
    RxAndroid…他にも ✤ RxLifecycle ✤ RxBinding ✤SqlBrite ✤ Android-ReactiveLocation ✤ rx-preferences
  • 25.
  • 26.
    Gradle の準備 // RxJava
 compile'io.reactivex:rxjava:1.0.15'
 
 // RXAndroid
 compile 'io.reactivex:rxandroid:1.0.1'
  • 27.
    Android Schedulers request().subscribeOn(Schedulers.newThread())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(new Observer<String>(){
 @Override
 public void onCompleted() {
 // network completed // main thread
 }
 
 @Override
 public void onError(Throwable e) {
 // network error
 // main thread
 }
 
 @Override
 public void onNext(String s) {
 // response call back
 // main thread
 }
 });
  • 28.
    Handler Schedulers Handler handler= new Handler();
 request().subscribeOn(Schedulers.newThread())
 .observeOn(HandlerScheduler.from(handler))
 .subscribe(new Observer<String>() {
 @Override
 public void onCompleted() {
 // network completed
 // handler thread
 }
 
 @Override
 public void onError(Throwable e) {
 // network error
 // handler thread
 }
 
 @Override
 public void onNext(String s) {
 // response call back
 // handler thread
 }
 });
  • 29.
  • 30.
  • 31.
    Retrofit ✤ A Typesafe HTTP client for Android and Java ✤ Android の為の REST 通信を手軽に実装できる!? ✤ Retrofit 2.0.0-bata2 を利用します。
  • 32.
    Retrofit ✤ 基本的な使い方 ✤ 非同期処理 ✤同期処理 ✤ RxJava を組み込んでみる
  • 33.
    Gradle の準備 // Retrofit
 compile‘com.squareup.retrofit:retrofit:2.0.0-beta2' // gson
 compile ‘com.google.code.gson:gson:2.4' // Converter Gson
 compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'

  • 34.
    Proguard の準備 # RetrofitProguard
 -dontwarn retrofit.**
 -keep class retrofit.** { *; }
 -keepattributes Signature
 -keepattributes Exceptions
  • 35.
  • 36.
    Model Class の作成 publicclass SignIn {
 @SerializedName("access_token")
 public final String accessToken;
 
 @SerializedName("user_id")
 public final int userId;
 
 @SerializedName("group_id")
 public final int group_id;
 
 public SignIn(String accessToken, int userId, int group_id) {
 this.accessToken = accessToken;
 this.userId = userId;
 this.group_id = group_id;
 }
 }
  • 37.
    Service Interface 作成 publicinterface UsersService {
 @FormUrlEncoded
 @POST("/v3/users/sign_in")
 Call<SignIn> signIn(@Field("email") String email, @Field("password") String password);
 }
  • 38.
    Service Interface 作成 publicinterface UsersService {
 @FormUrlEncoded
 @POST("/v3/users/sign_in")
 Call<SignIn> signIn(@Field("email") String email, @Field("password") String password);
 }
  • 39.
    非同期処理 // Gson ConverterFactory
 GsonConverterFactory factory = GsonConverterFactory.create(new Gson());
 
 // Retrofit
 Retrofit retrofit = new Retrofit.Builder()
 .baseUrl(baseUrl)
 .addConverterFactory(factory)
 .build();
 
 // Users Service
 UsersService usersService = retrofit.create(UsersService.class);
 
 // Call
 Call<SignIn> call = usersService.signIn(Email, Password);
 call.enqueue(new Callback<SignIn>() {
 @Override
 public void onResponse(Response<SignIn> response, Retrofit retrofit) {
 // network success
 }
 
 @Override
 public void onFailure(Throwable t) {
 // network error
 }
 });
  • 40.
    同期処理 // Gson ConverterFactory
 GsonConverterFactory factory = GsonConverterFactory.create(new Gson());
 
 // Retrofit
 Retrofit retrofit = new Retrofit.Builder()
 .baseUrl(baseUrl)
 .addConverterFactory(factory)
 .build();
 
 // Users Service
 UsersService usersService = retrofit.create(UsersService.class);
 
 // Call
 Call<SignIn> call = usersService.signIn(Email, Password);
 try {
 Response<SignIn> response = call.execute();
 } catch (IOException e) {
 e.printStackTrace();
 }
  • 41.
  • 42.
  • 43.
  • 44.
    Service Interface(RxJava版) public interfaceUsersService {
 @FormUrlEncoded
 @POST("/v3/users/sign_in")
 Observable<SignIn> signIn(@Field("email") String email, @Field("password") String password);
 }

  • 45.
    非同期処理(RxJava版) // Gson ConverterFactory
 GsonConverterFactory factory = GsonConverterFactory.create(new Gson());
 
 // RxJava Call Adapter
 RxJavaCallAdapterFactory adapterFactory = RxJavaCallAdapterFactory.create();
 
 // Retrofit
 Retrofit retrofit = new Retrofit.Builder()
 .baseUrl(baseUrl)
 .addConverterFactory(factory)
 .addCallAdapterFactory(adapterFactory)
 .build();
 
 // Users Service
 UsersService usersService = retrofit.create(UsersService.class);
 
 // User Service
 Observable<SignIn> observable = usersService.signIn(Email, Password);
 observable.subscribeOn(Schedulers.newThread())
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(new Observer<SignIn>() {
 @Override
 public void onCompleted() {
 // network completed
 }
 
 @Override
 public void onError(Throwable e) {
 // network error
 }
 
 @Override
 public void onNext(SignIn signIn) {
 // network success
 }
 });
  • 46.
    同期処理(RxJava版) // Gson ConverterFactory
 GsonConverterFactory factory = GsonConverterFactory.create(new Gson());
 
 // RxJava Call Adapter
 RxJavaCallAdapterFactory adapterFactory = RxJavaCallAdapterFactory.create();
 
 // Retrofit
 Retrofit retrofit = new Retrofit.Builder()
 .baseUrl(baseUrl)
 .addConverterFactory(factory)
 .addCallAdapterFactory(adapterFactory)
 .build();
 
 // Users Service
 UsersService usersService = retrofit.create(UsersService.class);
 
 // Call
 Observable<SignIn> observable = usersService.signIn(Email, Password);
 SignIn signIn = observable
 .subscribeOn(Schedulers.newThread())
 .toBlocking()
 .single();
 
 if (signIn == null) {
 // network error
 } else {
 // network success
 }
  • 47.
  • 48.
    Retrofit でハマったこと ✤ TwitterKit では Retrofit 1.8 を使っている ✤ Retrofit 1.8-1.9 と Retrofit 2.0 で設定の変更 ✤ Retrofit 2.0 では、RxJava の Call Adapter が必要
  • 49.