From 3ed00ff05897a855dab4a5d6a77a85a18ab54022 Mon Sep 17 00:00:00 2001 From: Prat Date: Wed, 16 Sep 2015 20:20:13 -0400 Subject: [PATCH 001/133] Update to Retrofit 2 --- app/build.gradle | 4 +- .../fragments/PseudoCacheConcatFragment.java | 33 ++++++++---- .../fragments/PseudoCacheMergeFragment.java | 36 +++++++++---- .../RetrofitAsyncTaskDeathFragment.java | 36 +++++++++---- .../rxjava/fragments/RetrofitFragment.java | 51 ++++++++++++------- 5 files changed, 113 insertions(+), 47 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8fedb1bc..6aef59f5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,7 +12,9 @@ dependencies { compile 'com.jakewharton:butterknife:5.1.1' compile 'com.jakewharton.timber:timber:2.4.2' - compile 'com.squareup.retrofit:retrofit:1.6.1' + compile 'com.squareup.retrofit:retrofit:2.0.0-beta1' + compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1' + compile 'com.squareup.retrofit:converter-gson:2.0.0-beta1' compile 'com.squareup.okhttp:okhttp:2.0.0' compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0' diff --git a/app/src/main/java/com/morihacky/android/rxjava/fragments/PseudoCacheConcatFragment.java b/app/src/main/java/com/morihacky/android/rxjava/fragments/PseudoCacheConcatFragment.java index c7496074..d06a8236 100644 --- a/app/src/main/java/com/morihacky/android/rxjava/fragments/PseudoCacheConcatFragment.java +++ b/app/src/main/java/com/morihacky/android/rxjava/fragments/PseudoCacheConcatFragment.java @@ -14,11 +14,19 @@ import com.morihacky.android.rxjava.R; import com.morihacky.android.rxjava.retrofit.Contributor; import com.morihacky.android.rxjava.retrofit.GithubApi; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import retrofit.RequestInterceptor; -import retrofit.RestAdapter; + +import retrofit.GsonConverterFactory; +import retrofit.Retrofit; +import retrofit.RxJavaCallAdapterFactory; import rx.Observable; import rx.Subscriber; import rx.Subscription; @@ -123,19 +131,26 @@ public Observable call(List contributors) { } private GithubApi _createGithubApi() { - - RestAdapter.Builder builder = new RestAdapter.Builder().setEndpoint( - "https://api.github.com/"); - //.setLogLevel(RestAdapter.LogLevel.FULL); + Retrofit.Builder builder =new Retrofit.Builder() + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + .addConverterFactory(GsonConverterFactory.create()) + .baseUrl("https://api.github.com"); final String githubToken = getResources().getString(R.string.github_oauth_token); + if (!TextUtils.isEmpty(githubToken)) { - builder.setRequestInterceptor(new RequestInterceptor() { + OkHttpClient client = new OkHttpClient(); + client.interceptors().add(new Interceptor() { @Override - public void intercept(RequestFacade request) { - request.addHeader("Authorization", format("token %s", githubToken)); + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Request newReq = request.newBuilder() + .addHeader("Authorization", format("token %s", githubToken)) + .build(); + return chain.proceed(newReq); } }); + builder.client(client); } return builder.build().create(GithubApi.class); diff --git a/app/src/main/java/com/morihacky/android/rxjava/fragments/PseudoCacheMergeFragment.java b/app/src/main/java/com/morihacky/android/rxjava/fragments/PseudoCacheMergeFragment.java index 17c6a6d5..720261ae 100644 --- a/app/src/main/java/com/morihacky/android/rxjava/fragments/PseudoCacheMergeFragment.java +++ b/app/src/main/java/com/morihacky/android/rxjava/fragments/PseudoCacheMergeFragment.java @@ -2,6 +2,7 @@ import android.os.Bundle; import android.support.annotation.Nullable; +import android.text.TextUtils; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; @@ -14,11 +15,19 @@ import com.morihacky.android.rxjava.R; import com.morihacky.android.rxjava.retrofit.Contributor; import com.morihacky.android.rxjava.retrofit.GithubApi; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import retrofit.RequestInterceptor; -import retrofit.RestAdapter; + +import retrofit.GsonConverterFactory; +import retrofit.Retrofit; +import retrofit.RxJavaCallAdapterFactory; import rx.Observable; import rx.Subscriber; import rx.Subscription; @@ -144,19 +153,26 @@ public Pair call(Contributor contributor) { } private GithubApi _createGithubApi() { - - RestAdapter.Builder builder = new RestAdapter.Builder().setEndpoint( - "https://api.github.com/"); - //.setLogLevel(RestAdapter.LogLevel.FULL); + Retrofit.Builder builder = new Retrofit.Builder() + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + .addConverterFactory(GsonConverterFactory.create()) + .baseUrl("https://api.github.com"); final String githubToken = getResources().getString(R.string.github_oauth_token); - if (!isEmpty(githubToken)) { - builder.setRequestInterceptor(new RequestInterceptor() { + + if (!TextUtils.isEmpty(githubToken)) { + OkHttpClient client = new OkHttpClient(); + client.interceptors().add(new Interceptor() { @Override - public void intercept(RequestFacade request) { - request.addHeader("Authorization", format("token %s", githubToken)); + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Request newReq = request.newBuilder() + .addHeader("Authorization", format("token %s", githubToken)) + .build(); + return chain.proceed(newReq); } }); + builder.client(client); } return builder.build().create(GithubApi.class); diff --git a/app/src/main/java/com/morihacky/android/rxjava/fragments/RetrofitAsyncTaskDeathFragment.java b/app/src/main/java/com/morihacky/android/rxjava/fragments/RetrofitAsyncTaskDeathFragment.java index 5e6a48c1..75b909ab 100644 --- a/app/src/main/java/com/morihacky/android/rxjava/fragments/RetrofitAsyncTaskDeathFragment.java +++ b/app/src/main/java/com/morihacky/android/rxjava/fragments/RetrofitAsyncTaskDeathFragment.java @@ -4,6 +4,7 @@ import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; +import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -16,9 +17,17 @@ import com.morihacky.android.rxjava.R; import com.morihacky.android.rxjava.retrofit.GithubApi; import com.morihacky.android.rxjava.retrofit.User; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +import java.io.IOException; import java.util.ArrayList; -import retrofit.RequestInterceptor; -import retrofit.RestAdapter; + +import retrofit.GsonConverterFactory; +import retrofit.Retrofit; +import retrofit.RxJavaCallAdapterFactory; import rx.Observer; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; @@ -102,19 +111,26 @@ public void onNext(User user) { // ----------------------------------------------------------------------------------- private GithubApi _createGithubApi() { - - RestAdapter.Builder builder = new RestAdapter.Builder().setEndpoint( - "https://api.github.com/"); - //.setLogLevel(RestAdapter.LogLevel.FULL); + Retrofit.Builder builder = new Retrofit.Builder() + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + .addConverterFactory(GsonConverterFactory.create()) + .baseUrl("https://api.github.com"); final String githubToken = getResources().getString(R.string.github_oauth_token); - if (!isEmpty(githubToken)) { - builder.setRequestInterceptor(new RequestInterceptor() { + + if (!TextUtils.isEmpty(githubToken)) { + OkHttpClient client = new OkHttpClient(); + client.interceptors().add(new Interceptor() { @Override - public void intercept(RequestFacade request) { - request.addHeader("Authorization", format("token %s", githubToken)); + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Request newReq = request.newBuilder() + .addHeader("Authorization", format("token %s", githubToken)) + .build(); + return chain.proceed(newReq); } }); + builder.client(client); } return builder.build().create(GithubApi.class); diff --git a/app/src/main/java/com/morihacky/android/rxjava/fragments/RetrofitFragment.java b/app/src/main/java/com/morihacky/android/rxjava/fragments/RetrofitFragment.java index 13e53c89..6727654a 100644 --- a/app/src/main/java/com/morihacky/android/rxjava/fragments/RetrofitFragment.java +++ b/app/src/main/java/com/morihacky/android/rxjava/fragments/RetrofitFragment.java @@ -1,8 +1,19 @@ package com.morihacky.android.rxjava.fragments; +import com.morihacky.android.rxjava.R; +import com.morihacky.android.rxjava.RxUtils; +import com.morihacky.android.rxjava.retrofit.Contributor; +import com.morihacky.android.rxjava.retrofit.GithubApi; +import com.morihacky.android.rxjava.retrofit.User; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; +import android.text.TextUtils; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; @@ -10,18 +21,17 @@ import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ListView; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + import butterknife.ButterKnife; import butterknife.InjectView; import butterknife.OnClick; -import com.morihacky.android.rxjava.R; -import com.morihacky.android.rxjava.RxUtils; -import com.morihacky.android.rxjava.retrofit.Contributor; -import com.morihacky.android.rxjava.retrofit.GithubApi; -import com.morihacky.android.rxjava.retrofit.User; -import java.util.ArrayList; -import java.util.List; -import retrofit.RequestInterceptor; -import retrofit.RestAdapter; +import retrofit.GsonConverterFactory; +import retrofit.Retrofit; +import retrofit.RxJavaCallAdapterFactory; import rx.Observable; import rx.Observer; import rx.android.schedulers.AndroidSchedulers; @@ -192,19 +202,26 @@ public void onNext(Pair pair) { // ----------------------------------------------------------------------------------- private GithubApi _createGithubApi() { - - RestAdapter.Builder builder = new RestAdapter.Builder().setEndpoint( - "https://api.github.com/"); - //.setLogLevel(RestAdapter.LogLevel.FULL); + Retrofit.Builder builder = new Retrofit.Builder() + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + .addConverterFactory(GsonConverterFactory.create()) + .baseUrl("https://api.github.com"); final String githubToken = getResources().getString(R.string.github_oauth_token); - if (!isEmpty(githubToken)) { - builder.setRequestInterceptor(new RequestInterceptor() { + + if (!TextUtils.isEmpty(githubToken)) { + OkHttpClient client = new OkHttpClient(); + client.interceptors().add(new Interceptor() { @Override - public void intercept(RequestFacade request) { - request.addHeader("Authorization", format("token %s", githubToken)); + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Request newReq = request.newBuilder() + .addHeader("Authorization", format("token %s", githubToken)) + .build(); + return chain.proceed(newReq); } }); + builder.client(client); } return builder.build().create(GithubApi.class); From ddcbefc198f95696f50df6d5614b7513e29b5925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=A5=BF=E6=B6=9B?= Date: Wed, 30 Dec 2015 15:44:47 +0800 Subject: [PATCH 002/133] volley rx demo --- app/build.gradle | 4 +- .../com/morihacky/android/rxjava/MyApp.java | 5 + .../rxjava/fragments/MainFragment.java | 11 +- .../rxjava/fragments/VolleyDemoFragment.java | 189 ++++++++++++++++++ .../android/rxjava/wiring/MyVolley.java | 63 ++++++ app/src/main/res/layout/fragment_main.xml | 6 + app/src/main/res/layout/fragment_volley.xml | 34 ++++ app/src/main/res/values/strings.xml | 3 +- 8 files changed, 311 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/morihacky/android/rxjava/fragments/VolleyDemoFragment.java create mode 100644 app/src/main/java/com/morihacky/android/rxjava/wiring/MyVolley.java create mode 100644 app/src/main/res/layout/fragment_volley.xml diff --git a/app/build.gradle b/app/build.gradle index d11bcaa8..164fdf86 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,6 +18,8 @@ dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3' + compile 'com.mcxiaoke.volley:library:1.0.19' + } android { @@ -37,4 +39,4 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/morihacky/android/rxjava/MyApp.java b/app/src/main/java/com/morihacky/android/rxjava/MyApp.java index b66f855f..f6f18c97 100644 --- a/app/src/main/java/com/morihacky/android/rxjava/MyApp.java +++ b/app/src/main/java/com/morihacky/android/rxjava/MyApp.java @@ -1,6 +1,8 @@ package com.morihacky.android.rxjava; import android.app.Application; + +import com.morihacky.android.rxjava.wiring.MyVolley; import com.squareup.leakcanary.LeakCanary; import com.squareup.leakcanary.RefWatcher; import timber.log.Timber; @@ -27,5 +29,8 @@ public void onCreate() { _refWatcher = LeakCanary.install(this); Timber.plant(new Timber.DebugTree()); + + //volley init + MyVolley.init(this); } } diff --git a/app/src/main/java/com/morihacky/android/rxjava/fragments/MainFragment.java b/app/src/main/java/com/morihacky/android/rxjava/fragments/MainFragment.java index 030e9503..05efda07 100644 --- a/app/src/main/java/com/morihacky/android/rxjava/fragments/MainFragment.java +++ b/app/src/main/java/com/morihacky/android/rxjava/fragments/MainFragment.java @@ -7,11 +7,13 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import butterknife.ButterKnife; -import butterknife.OnClick; + import com.morihacky.android.rxjava.R; import com.morihacky.android.rxjava.rxbus.RxBusDemoFragment; +import butterknife.ButterKnife; +import butterknife.OnClick; + public class MainFragment extends BaseFragment { @@ -80,6 +82,11 @@ void demoRotationPersist() { //clickedOn(new RotationPersist1Fragment()); } + @OnClick(R.id.btn_demo_volley) + void demoVolleyRequest() { + clickedOn(new VolleyDemoFragment()); + } + private void clickedOn(@NonNull Fragment fragment) { final String tag = fragment.getClass().toString(); getActivity().getSupportFragmentManager() diff --git a/app/src/main/java/com/morihacky/android/rxjava/fragments/VolleyDemoFragment.java b/app/src/main/java/com/morihacky/android/rxjava/fragments/VolleyDemoFragment.java new file mode 100644 index 00000000..a37f1810 --- /dev/null +++ b/app/src/main/java/com/morihacky/android/rxjava/fragments/VolleyDemoFragment.java @@ -0,0 +1,189 @@ +package com.morihacky.android.rxjava.fragments; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.support.annotation.Nullable; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ListView; + +import com.android.volley.Request; +import com.android.volley.VolleyError; +import com.android.volley.toolbox.JsonObjectRequest; +import com.android.volley.toolbox.RequestFuture; +import com.morihacky.android.rxjava.R; +import com.morihacky.android.rxjava.wiring.LogAdapter; +import com.morihacky.android.rxjava.wiring.MyVolley; + +import org.json.JSONObject; + +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; + +import butterknife.Bind; +import butterknife.ButterKnife; +import butterknife.OnClick; +import rx.Observable; +import rx.Observer; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Func0; +import rx.schedulers.Schedulers; +import rx.subscriptions.CompositeSubscription; +import timber.log.Timber; + +/** + * Created by zhangxitao on 15/12/30. + */ + +public class VolleyDemoFragment + extends BaseFragment { + public static final String TAG = "VolleyDemoFragment"; + + @Bind(R.id.list_threading_log) + ListView _logsList; + @Bind(R.id.btn_start_operation) + Button _tapBtn; + + private LogAdapter _adapter; + private List _logs; + + private CompositeSubscription mCompositeSubscription = new CompositeSubscription(); + + @OnClick(R.id.btn_start_operation) + void startRequest() { + startVolleyRequest(); + } + + + @Override + public void onStart() { + super.onStart(); + + /** + * @condition: RxJava future request with volley + */ + } + + @Override + public void onPause() { + super.onPause(); + mCompositeSubscription.unsubscribe(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + _setupLogger(); + } + + @Override + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + View layout = inflater.inflate(R.layout.fragment_volley, container, false); + ButterKnife.bind(this, layout); + return layout; + } + + private void startVolleyRequest() { + mCompositeSubscription.add(newGetRouteData() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer() { + @Override + public void onCompleted() { + Log.e(TAG, "onCompleted"); + Timber.d("----- onCompleted"); + _log("onCompleted "); + } + + @Override + public void onError(Throwable e) { + VolleyError cause = (VolleyError) e.getCause(); + String s = new String(cause.networkResponse.data, Charset.forName("UTF-8")); + Log.e(TAG, s); + Log.e(TAG, cause.toString()); + _log("onError " + s); + + } + + @Override + public void onNext(JSONObject jsonObject) { + Log.e(TAG, "onNext " + jsonObject.toString()); + _log("onNext " + jsonObject.toString()); + + } + })); + } + + + /** + * @use handle response from future request, in my case JsonObject. + */ + private JSONObject getRouteData() throws ExecutionException, InterruptedException { + RequestFuture future = RequestFuture.newFuture(); + String url = "http://www.weather.com.cn/adat/sk/101010100.html"; + final Request.Priority priority = Request.Priority.IMMEDIATE; + JsonObjectRequest req = new JsonObjectRequest(Request.Method.GET, url, future, future); + MyVolley.getRequestQueue().add(req); + return future.get(); + } + + /** + * @use the observable, same type data Jsob Object + */ + public Observable newGetRouteData() { + return Observable.defer(new Func0>() { + @Override + public Observable call() { + Exception exception; + try { + return Observable.just(getRouteData()); + } catch (InterruptedException | ExecutionException e) { + Log.e("routes", e.getMessage()); + return Observable.error(e); + } + } + }); + } + + // ----------------------------------------------------------------------------------- + // Methods that help wiring up the example (irrelevant to RxJava) + + private void _setupLogger() { + _logs = new ArrayList<>(); + _adapter = new LogAdapter(getActivity(), new ArrayList()); + _logsList.setAdapter(_adapter); + } + + private void _log(String logMsg) { + + if (_isCurrentlyOnMainThread()) { + _logs.add(0, logMsg + " (main thread) "); + _adapter.clear(); + _adapter.addAll(_logs); + } else { + _logs.add(0, logMsg + " (NOT main thread) "); + + // You can only do below stuff on main thread. + new Handler(Looper.getMainLooper()).post(new Runnable() { + + @Override + public void run() { + _adapter.clear(); + _adapter.addAll(_logs); + } + }); + } + } + + private boolean _isCurrentlyOnMainThread() { + return Looper.myLooper() == Looper.getMainLooper(); + } +} diff --git a/app/src/main/java/com/morihacky/android/rxjava/wiring/MyVolley.java b/app/src/main/java/com/morihacky/android/rxjava/wiring/MyVolley.java new file mode 100644 index 00000000..9f2a2534 --- /dev/null +++ b/app/src/main/java/com/morihacky/android/rxjava/wiring/MyVolley.java @@ -0,0 +1,63 @@ +package com.morihacky.android.rxjava.wiring; + +/** + * Created by zhangxitao on 15/9/7. + */ + +import android.app.ActivityManager; +import android.content.Context; + +import com.android.volley.RequestQueue; +import com.android.volley.toolbox.ImageLoader; +import com.android.volley.toolbox.Volley; + +/** + * Helper class that is used to provide references to initialized RequestQueue(s) and ImageLoader(s) + * + * @author Ognyan Bankov + */ +public class MyVolley { + private static RequestQueue mRequestQueue; + private static ImageLoader mImageLoader; + + + private MyVolley() { + // no instances + } + + + public static void init(Context context) { + mRequestQueue = Volley.newRequestQueue(context); + + int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)) + .getMemoryClass(); + // Use 1/8th of the available memory for this memory cache. + int cacheSize = 1024 * 1024 * memClass / 8; +// mImageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache(cacheSize)); + } + + + public static RequestQueue getRequestQueue() { + if (mRequestQueue != null) { + return mRequestQueue; + } else { + throw new IllegalStateException("RequestQueue not initialized"); + } + } + + + /** + * Returns instance of ImageLoader initialized with {@see FakeImageCache} which effectively means + * that no memory caching is used. This is useful for images that you know that will be show + * only once. + * + * @return + */ + public static ImageLoader getImageLoader() { + if (mImageLoader != null) { + return mImageLoader; + } else { + throw new IllegalStateException("ImageLoader not initialized"); + } + } +} diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml index 0f06a098..aba0cd1d 100644 --- a/app/src/main/res/layout/fragment_main.xml +++ b/app/src/main/res/layout/fragment_main.xml @@ -100,5 +100,11 @@ android:layout_width="match_parent" android:text="@string/btn_demo_rotation_persist" /> +