├── .gitignore
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ ├── four
│ │ ├── 00.jpg
│ │ ├── 132.jpg
│ │ └── guangtouge04.png
│ ├── one
│ │ ├── 00.jpg
│ │ └── guangtouge01.png
│ ├── three
│ │ ├── 132.jpg
│ │ └── guangtouge03.png
│ └── two
│ │ ├── 40.jpg
│ │ └── guangtouge02.png
│ ├── java
│ └── com
│ │ └── malin
│ │ └── rxjava
│ │ ├── activity
│ │ └── MainActivity.java
│ │ ├── application
│ │ └── RxJavaApplication.java
│ │ ├── constant
│ │ └── Constant.java
│ │ ├── factory
│ │ ├── DataFactory.java
│ │ └── ImageNameFactory.java
│ │ ├── githubapi
│ │ └── GitHubApi.java
│ │ ├── model
│ │ ├── Contributor.java
│ │ ├── Course.java
│ │ ├── Student.java
│ │ └── User.java
│ │ ├── service
│ │ └── RetrofitService.java
│ │ └── utils
│ │ ├── ClickUtils.java
│ │ ├── DeviceInfo.java
│ │ ├── ImageUtils.java
│ │ ├── RecycleBitmap.java
│ │ ├── RxUtils.java
│ │ └── ToastUtil.java
│ └── res
│ ├── layout
│ ├── activity_main.xml
│ └── item_log.xml
│ ├── mipmap-xhdpi
│ └── malin.jpg
│ ├── values-w820dp
│ └── dimens.xml
│ ├── values-zh
│ └── strings.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── qrcode
└── dowload_qrcode.png
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /products
3 | .gradle
4 | /.idea/workspace.xml
5 | .idea
6 | /.idea/
7 | /local.properties
8 | *.iml
9 | /modules
10 | .settings.gradle
11 |
12 |
13 | # built application files
14 | *.ap_
15 |
16 | # files for the dex VM
17 | *.dex
18 | # Java class files
19 | *.class
20 |
21 | # generated files
22 | bin/
23 | gen/
24 | *target/
25 | *build/
26 | .gradle/
27 | .idea/
28 | RengwuxianRxjava.iml
29 | gradle.properties
30 | /gradle.properties
31 | gen-external-apklibs/
32 |
33 | # Eclipse project files
34 | .classpath
35 | .project
36 |
37 | # Mac os
38 | .DS_Store
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 malin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## RxJava
2 | RxJava之扔物线[给Android开发者的RxJava详解](http://gank.io/post/560e15be2dca930e00da1083)文章中的例子
3 |
4 | ### Build
5 |
6 | To build:
7 | >$ git clone https://github.com/androidmalin/RengwuxianRxjava.git
8 | >$ cd RengwuxianRxjava/
9 | >$ gradle clean --stacktrace(./gradlew clean --stacktrace )
10 |
11 |
12 | ### Bugs and Feedback
13 |
14 | For bugs, questions and discussions please use the [Github Issues](https://github.com/androidmalin/RengwuxianRxjava/issues).
15 |
16 |
17 | ### 项目依赖
18 |
19 | 项目名称 | 项目信息
20 | ------- | -------
21 | [android.support.*](https://developer.android.com/tools/support-library/index.html) | Android Support Library
22 | [RxJava](https://github.com/ReactiveX/RxJava) | 一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库
23 | [RxAndroid](https://github.com/ReactiveX/RxAndroid) | RxAndroid 是 RxJava 的一个针对 Android 平台的扩展
24 | [RxBinding](https://github.com/JakeWharton/RxBinding) | JakeWharton Android函数式相应编程(FRP)框架
25 | [logger](https://github.com/orhanobut/logger) | 一个简洁,优雅,功能强大的Android日志输出工具
26 |
27 |
28 | ### 参考的文章
29 | 作者 | 文章| 参考的地方
30 | ------- | -------| -------
31 | [扔物线](https://github.com/rengwuxian) | [给Android开发者的RxJava详解](http://gank.io/post/560e15be2dca930e00da1083) | 示例代码
32 | [胡凯](https://github.com/kesenhoo) | [ 高效加载大图](http://hukai.me/android-training-course-in-chinese/graphics/displaying-bitmaps/load-bitmap.html) | Bitmap压缩算法
33 | [intbird](http://blog.csdn.net/intbird) | [Android OOM ,回收布局文件中ImageView占用的内存.Bitmap OOM回收解决.](http://blog.csdn.net/intbird/article/details/19905549) | Bitmap回收
34 | [任玉刚](https://github.com/singwhatiwanna)|[Android开发艺术探索](https://item.jd.com/11760209.html) | BitmapFactory解析的配置
35 | [徐宜生](https://github.com/xuyisheng)|[Android群英传](https://item.jd.com/11758334.html)| Canvas的使用
36 | [shwenzhang](https://github.com/shwenzhang)|[Android内存优化杂谈](http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=400656149&idx=1&sn=122b4f4965fafebf78ec0b4fce2ef62a&3rd=MzA3MDU4NTYzMw==&scene=6#rd)| 内存优化
37 |
38 |
39 | ### About me
40 |
41 | [我的CSDN博客](http://blog.csdn.net/androidmalin):[http://blog.csdn.net/androidmalin](http://blog.csdn.net/androidmalin)
42 | [我的微博](http://weibo.com/androidmalin):[http://weibo.com/androidmalin](http://weibo.com/androidmalin)
43 |
44 |
45 | ### License
46 |
47 | The MIT License (MIT)
48 |
49 | Copyright (c) 2015 malin
50 |
51 | Permission is hereby granted, free of charge, to any person obtaining a copy
52 | of this software and associated documentation files (the "Software"), to deal
53 | in the Software without restriction, including without limitation the rights
54 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
55 | copies of the Software, and to permit persons to whom the Software is
56 | furnished to do so, subject to the following conditions:
57 |
58 | The above copyright notice and this permission notice shall be included in all
59 | copies or substantial portions of the Software.
60 |
61 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
64 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
65 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
66 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
67 | SOFTWARE.
68 |
69 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /app.iml
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | android {
3 | compileSdkVersion 23
4 | buildToolsVersion '23.0.3'
5 |
6 |
7 | defaultConfig {
8 | applicationId "com.malin.rengwuxianrxjava"
9 | minSdkVersion 16
10 | targetSdkVersion 23
11 | versionCode 16
12 | versionName "1.16"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 |
21 | lintOptions {
22 | abortOnError false
23 | }
24 |
25 | compileOptions {
26 | sourceCompatibility JavaVersion.VERSION_1_7
27 | targetCompatibility JavaVersion.VERSION_1_7
28 | }
29 | }
30 |
31 | //add for logger
32 | repositories {
33 | jcenter()
34 | maven { url "https://jitpack.io" }
35 | mavenCentral()
36 | }
37 | dependencies {
38 |
39 | compile 'com.android.support:design:23.4.0'
40 | compile 'com.android.support:appcompat-v7:23.4.0'
41 | compile 'com.github.orhanobut:logger:1.12'
42 | compile 'com.jakewharton.rxbinding:rxbinding:0.3.0'
43 | compile 'com.squareup.retrofit2:retrofit:2.0.2'
44 | compile 'com.squareup.retrofit2:retrofit:2.0.2'
45 | compile 'com.squareup.retrofit2:converter-gson:2.0.2'
46 | compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
47 | compile 'io.reactivex:rxandroid:1.1.0'
48 |
49 | }
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/malin/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/assets/four/00.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidmalin/RxjavaSample/3a13759b2db1105024b94be75ad81906a00b59c8/app/src/main/assets/four/00.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/four/132.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidmalin/RxjavaSample/3a13759b2db1105024b94be75ad81906a00b59c8/app/src/main/assets/four/132.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/four/guangtouge04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidmalin/RxjavaSample/3a13759b2db1105024b94be75ad81906a00b59c8/app/src/main/assets/four/guangtouge04.png
--------------------------------------------------------------------------------
/app/src/main/assets/one/00.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidmalin/RxjavaSample/3a13759b2db1105024b94be75ad81906a00b59c8/app/src/main/assets/one/00.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/one/guangtouge01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidmalin/RxjavaSample/3a13759b2db1105024b94be75ad81906a00b59c8/app/src/main/assets/one/guangtouge01.png
--------------------------------------------------------------------------------
/app/src/main/assets/three/132.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidmalin/RxjavaSample/3a13759b2db1105024b94be75ad81906a00b59c8/app/src/main/assets/three/132.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/three/guangtouge03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidmalin/RxjavaSample/3a13759b2db1105024b94be75ad81906a00b59c8/app/src/main/assets/three/guangtouge03.png
--------------------------------------------------------------------------------
/app/src/main/assets/two/40.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidmalin/RxjavaSample/3a13759b2db1105024b94be75ad81906a00b59c8/app/src/main/assets/two/40.jpg
--------------------------------------------------------------------------------
/app/src/main/assets/two/guangtouge02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidmalin/RxjavaSample/3a13759b2db1105024b94be75ad81906a00b59c8/app/src/main/assets/two/guangtouge02.png
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.activity;
27 |
28 | import android.content.Context;
29 | import android.graphics.Bitmap;
30 | import android.graphics.Canvas;
31 | import android.graphics.Paint;
32 | import android.graphics.PorterDuff;
33 | import android.graphics.PorterDuffXfermode;
34 | import android.graphics.drawable.Drawable;
35 | import android.os.Bundle;
36 | import android.support.v4.content.ContextCompat;
37 | import android.support.v7.app.AppCompatActivity;
38 | import android.text.TextUtils;
39 | import android.util.Log;
40 | import android.view.View;
41 | import android.view.ViewGroup;
42 | import android.widget.AdapterView;
43 | import android.widget.ArrayAdapter;
44 | import android.widget.EditText;
45 | import android.widget.ImageView;
46 | import android.widget.ListView;
47 | import android.widget.ProgressBar;
48 | import android.widget.TextView;
49 | import android.widget.Toast;
50 |
51 | import com.jakewharton.rxbinding.view.RxView;
52 | import com.jakewharton.rxbinding.widget.RxTextView;
53 | import com.jakewharton.rxbinding.widget.TextViewTextChangeEvent;
54 | import com.malin.rxjava.R;
55 | import com.malin.rxjava.application.RxJavaApplication;
56 | import com.malin.rxjava.constant.Constant;
57 | import com.malin.rxjava.factory.DataFactory;
58 | import com.malin.rxjava.factory.ImageNameFactory;
59 | import com.malin.rxjava.githubapi.GitHubApi;
60 | import com.malin.rxjava.model.Contributor;
61 | import com.malin.rxjava.model.Course;
62 | import com.malin.rxjava.model.Student;
63 | import com.malin.rxjava.model.User;
64 | import com.malin.rxjava.service.RetrofitService;
65 | import com.malin.rxjava.utils.ClickUtils;
66 | import com.malin.rxjava.utils.DeviceInfo;
67 | import com.malin.rxjava.utils.ImageUtils;
68 | import com.malin.rxjava.utils.RecycleBitmap;
69 | import com.malin.rxjava.utils.RxUtils;
70 | import com.malin.rxjava.utils.ToastUtil;
71 | import com.orhanobut.logger.LogLevel;
72 | import com.orhanobut.logger.Logger;
73 |
74 | import java.io.IOException;
75 | import java.text.SimpleDateFormat;
76 | import java.util.ArrayList;
77 | import java.util.Date;
78 | import java.util.List;
79 | import java.util.Locale;
80 | import java.util.concurrent.TimeUnit;
81 |
82 | import okhttp3.ResponseBody;
83 | import retrofit2.Call;
84 | import retrofit2.Callback;
85 | import retrofit2.Response;
86 | import rx.Observable;
87 | import rx.Observer;
88 | import rx.Subscriber;
89 | import rx.android.schedulers.AndroidSchedulers;
90 | import rx.functions.Action0;
91 | import rx.functions.Action1;
92 | import rx.functions.Func1;
93 | import rx.schedulers.Schedulers;
94 | import rx.subscriptions.CompositeSubscription;
95 |
96 |
97 | /**
98 | * 类描述:活动主页面
99 | * 创建人:malin.myemail@gmail.com
100 | * 创建时间:15-11-10.
101 | * 备注:
102 | */
103 | public class MainActivity extends AppCompatActivity {
104 | private static final String TAG = "MainActivity";
105 | private static final String TAG_FOR_LOGGER = "MainActivity_I_LOVE_RXJAVA";
106 | private static final String ERROR = "故意让程序出错";
107 | private static final String JPG = ".jpg";
108 | private int mCounter;//循环的计数器
109 | private ImageView mImageView;
110 | private Bitmap mManyBitmapSuperposition = null;
111 | private Canvas mCanvas = null;
112 | private ProgressBar mProgressBar;
113 | private EditText mSearchEditText;
114 | private TextView mResultTextView;
115 | private Context mContext;
116 |
117 | @Override
118 | protected void onCreate(Bundle savedInstanceState) {
119 | super.onCreate(savedInstanceState);
120 | setContentView(R.layout.activity_main);
121 | initializeLogAndDeviceInfo();
122 | initView();
123 | initData();
124 | testFuncation(9);//RxJava基础概念的练习
125 | }
126 |
127 | /**
128 | * 初始化Logger日志输出配置和获取手机尺寸信息
129 | */
130 | private void initializeLogAndDeviceInfo() {
131 | Logger.init(TAG_FOR_LOGGER).logLevel(LogLevel.FULL);//Use LogLevel.NONE for the release versions.
132 | DeviceInfo.getInstance().initializeScreenInfo(this);
133 | }
134 |
135 | /**
136 | * 用于显示图片的初始化
137 | */
138 | private void initView() {
139 | mContext = this;
140 | mImageView = (ImageView) findViewById(R.id.iv_image);
141 | mResultTextView = (TextView) findViewById(R.id.tv_result);
142 | mSearchEditText = (EditText) findViewById(R.id.ed_search);
143 | mProgressBar = (ProgressBar) findViewById(R.id.progressbar);
144 | }
145 |
146 | private void initData() {
147 | mContext = this;
148 | }
149 |
150 | /**
151 | * 故意让程序出现异常,可以用来测试
152 | */
153 | private void getException() {
154 | int errorCode = Integer.valueOf(ERROR);
155 | }
156 |
157 | //-----------------------------------------------0:RxJava基础练习-----------------------------------------------------------
158 | //概念解释
159 | //1:被观察者,事件源:它决定什么时候触发事件以及触发怎样的事件
160 | //2:观察者:它决定事件触发的时候将有怎样的行为
161 | //3:订阅
162 | private void method0() {
163 |
164 | //1:被观察者,事件源
165 | //概念解释:RxJava 使用 Observable.create() 方法来创建一个 Observable ,并为它定义事件触发规则
166 | Observable observable = Observable.create(new Observable.OnSubscribe() {
167 | @Override
168 | public void call(Subscriber super String> subscriber) {
169 | subscriber.onNext("Hello");
170 | subscriber.onNext("World");
171 | subscriber.onNext("!");
172 | subscriber.onCompleted();
173 | subscriber.onError(new Throwable());
174 | Logger.d("被观察者-observable->call()->onCompleted()之后是否还有输出");
175 | }
176 | });
177 |
178 | /**
179 | * 可以看到,这里传入了一个 OnSubscribe 对象作为参数。
180 | * OnSubscribe 会被存储在返回的 Observable 对象中,它的作用相当于一个计划表,
181 | * 当Observable 被订阅的时候,OnSubscribe 的 call() 方法会自动被调用,事件序列就会依照设定依次触发
182 | * (对于上面的代码,就是观察者subscriber 将会被调用三次 onNext() 和一次 onCompleted())。
183 | * 这样,由被观察者调用了观察者的回调方法,就实现了由被观察者向观察者的事件传递,即观察者模式。
184 | */
185 | //2:观察者
186 | Observer observer = new Observer() {
187 | @Override
188 | public void onCompleted() {
189 | Logger.d("观察者-observer:onCompleted()");
190 | }
191 |
192 | @Override
193 | public void onError(Throwable e) {
194 | Logger.d("观察者-observer:onError" + e.getMessage());
195 | }
196 |
197 | @Override
198 | public void onNext(String s) {
199 | Logger.d("观察者-observer:onNext():" + s);
200 | // getException();//故意让程序出现异常,用于测试onError()方法的执行....
201 | }
202 | };
203 |
204 | //3:订阅--被观察者被观察者订阅
205 | observable.subscribe(observer);
206 | }
207 |
208 |
209 | //---------------------------------------1:快捷创建事件队列 Observable.just(T...)--------------------------------------------------------------
210 |
211 | // create() 方法是 RxJava 最基本的创造事件序列的方法。基于这个方法, RxJava 还提供了一些方法用来快捷创建事件队列,
212 | // 例如just(T...): 将传入的参数依次发送出来.
213 |
214 | //简化:观察者的创建,RxJava快捷创建事件队列的方法:just(T...):
215 |
216 | /**
217 | * 简化:观察者的创建
218 | * {@link #method0()}
219 | */
220 | private void method1() {
221 |
222 |
223 | //实现步骤
224 | //1:被观察者:
225 | //2:观察者:
226 | //3:订阅-被观察者被观察者订阅
227 |
228 |
229 | //1:被观察者:
230 | //just(T...): 将传入的参数依次发送出来
231 | Observable observable = Observable.just("Hello", "World", "!");
232 | // 将会依次调用:
233 | // onNext("Hello");
234 | // onNext("World");
235 | // onNext("!");
236 | // onCompleted();
237 |
238 |
239 | //2:观察者:
240 | Observer observer = new Observer() {
241 | @Override
242 | public void onCompleted() {
243 | Logger.d("观察者-observer:onCompleted()");
244 | }
245 |
246 | @Override
247 | public void onError(Throwable e) {
248 | Logger.d("观察者-observer:onError()");
249 | }
250 |
251 | @Override
252 | public void onNext(String s) {
253 | Logger.d("观察者-observer:onNext():" + s);
254 | //getException();//故意让程序出现异常,用于测试onError()方法的执行....
255 | }
256 | };
257 |
258 | //3:订阅:被观察者被观察者订阅
259 | observable.subscribe(observer);
260 | }
261 |
262 |
263 | //---------------------------------------2:快捷创建事件队列 Observable.from(T[]) / from(Iterable extends T>--------------------------------------------------------------
264 |
265 | /**
266 | * 简化:观察者的创建: RxJava快捷创建事件队列的方法:just(String[] array) 将传入的数组或 Iterable 拆分成具体对象后,依次发送出来
267 | * {@link #method1()}
268 | */
269 | private void method2() {
270 |
271 | //实现步骤
272 | //1:被观察者
273 | //2:观察者
274 | //3:订阅-被观察者被观察者订阅
275 |
276 |
277 | String[] array = new String[]{"Hello", "World", "!"};
278 | //1:被观察者:
279 | //just(String[] array) 将传入的数组或 Iterable 拆分成具体对象后,依次发送出来。
280 | Observable observable = Observable.from(array);
281 | // 将会依次调用:
282 | // onNext("Hello");
283 | // onNext("World");
284 | // onNext("!");
285 | // onCompleted();
286 |
287 |
288 | //2:观察者
289 | Observer observer = new Observer() {
290 | @Override
291 | public void onCompleted() {
292 | Logger.d("观察者-observer:onCompleted()");
293 | }
294 |
295 | @Override
296 | public void onError(Throwable e) {
297 | Logger.d("观察者-observer:onError()");
298 | }
299 |
300 | @Override
301 | public void onNext(Object o) {
302 | String str = (String) o;
303 | Logger.d("观察者-observer:onNext():" + str);
304 | // getException();//故意让程序出现异常,用于测试onError()方法的执行....
305 | }
306 | };
307 |
308 | //3:订阅: 被观察者被观察者订阅
309 | observable.subscribe(observer);
310 |
311 | }
312 |
313 | //---------------------------------------3: subscribe()支持不完整定义的回调--------------------------------------------------------------
314 |
315 | /**
316 | * 对观察者的简化
317 | * {@link #method2()}
318 | * subscribe一个参数的不完整定义的回调
319 | * subscribe(final Action1 super T> onNext)
320 | */
321 | private void method3() {
322 |
323 | String[] array = new String[]{"Hello", "World", "!"};
324 | //1:被观察者
325 | Observable observable = Observable.from(array);
326 |
327 | //2:观察者
328 | Action1 onNextAction = new Action1() {
329 | @Override
330 | public void call(Object o) {
331 | String str = (String) o;
332 | Logger.d("观察者:call(Object o):" + str);
333 | }
334 | };
335 |
336 | //3:订阅-被观察者被观察者订阅
337 | //subscribe(final Action1 super T> onNext)
338 | //自动创建 Subscriber ,并使用 onNextAction 来定义 onNext()
339 | observable.subscribe(onNextAction);
340 | }
341 |
342 | /**
343 | * 对观察者的简化
344 | * subscribe两个参数的不完整定义的回调
345 | * {@link #method3()}
346 | * subscribe(final Action1 super T> onNext, final Action1 onError)
347 | */
348 | private void method4() {
349 |
350 | //1:被观察者
351 | Observable observable = Observable.from(new String[]{"Hello", "World", "!"});
352 |
353 | //2:观察者
354 | Action1 onNextAction = new Action1() {
355 | @Override
356 | public void call(Object o) {
357 | String str = (String) o;
358 | Logger.d("观察者:onNextAction:call(Object o):o:" + str);
359 | }
360 | };
361 |
362 |
363 | Action1 onErrorAction = new Action1() {
364 | @Override
365 | public void call(Throwable throwable) {
366 | Logger.d("观察者:onErrorAction:call(Throwable throwable):" + throwable.getMessage());
367 | }
368 | };
369 |
370 |
371 | //3:订阅
372 | //subscribe(final Action1 super T> onNext, final Action1 onError)
373 | // 自动创建 Subscriber ,并使用 onNextAction 和 onErrorAction 来定义 onNext() 和 onError()
374 | observable.subscribe(onNextAction, onErrorAction);
375 |
376 |
377 | }
378 |
379 | /**
380 | * subscribe三个参数的不完整定义的回调
381 | * subscribe(final Action1 super T> onNext, final Action1 onError, final Action0 onComplete)
382 | */
383 | private void method5() {
384 | //1:被观察者
385 | Observable observable = Observable.from(new String[]{"Hello", "World", "!"});
386 |
387 |
388 | //2:观察者
389 | Action1 onNextAction = new Action1() {
390 | @Override
391 | public void call(Object o) {
392 | String str = (String) o;
393 | Logger.d("观察者:onNextAction:call():s:" + str);
394 | }
395 | };
396 |
397 |
398 | Action1 onErrorAction = new Action1() {
399 | @Override
400 | public void call(Throwable throwable) {
401 | Logger.d("观察者:onErrorAction:call(Throwable throwable):" + throwable.getMessage());
402 | }
403 | };
404 |
405 |
406 | Action0 onCompletedAction = new Action0() {
407 | @Override
408 | public void call() {
409 | Logger.d("观察者:onCompletedAction:call()");
410 | }
411 | };
412 |
413 |
414 | //3:订阅:被观察者被观察者订阅
415 |
416 | //subscribe(final Action1 super T> onNext, final Action1 onError, final Action0 onComplete)
417 | // 自动创建 Subscriber ,并使用 onNextAction、 onErrorAction 和 onCompletedAction 来定义 onNext()、 onError() 和 onCompleted()
418 | observable.subscribe(onNextAction, onErrorAction, onCompletedAction);
419 |
420 | }
421 |
422 | //---------------------------------------4: Action0和Action1 讲解--------------------------------------------------------------
423 | /**
424 | * 肯定有同学对Action0和Action1很困惑,就像当初我刚看到那样子;
425 | * 那就听听扔物线给大家讲一下:
426 | *
427 | * MaLin:扔物线大哥,你能够给我们讲解一下Action0和Action1是什么,以及他们之间的区别吗?
428 | *
429 | * 扔物线:大家好,我简单的解释一下:
430 | * Action0 是 RxJava 的一个接口,它只有一个方法 call(),这个方法是无参无返回值的;
431 | * 由于 onCompleted() 方法也是无参无返回值的,因此 Action0 可以被当成一个包装对象,
432 | * 将 onCompleted() 的内容打包起来将自己作为一个参数传入 subscribe() 以实现不完整定义的回调。
433 | * 这样其实也可以看做将 onCompleted() 方法作为参数传进了 subscribe(),相当于其他某些语言中的『闭包』。
434 | *
435 | * Action1 也是一个接口,它同样只有一个方法 call(T param),这个方法也无返回值,但有一个参数;
436 | * 与 Action0 同理,由于 onNext(T obj) 和 onError(Throwable error) 也是单参数无返回值的,
437 | * 因此 Action1 可以将 onNext(obj) 和 onError(error) 打包起来传入 subscribe() 以实现不完整定义的回调。
438 | * 事实上,虽然 Action0 和 Action1 在 API 中使用最广泛,但 RxJava 是提供了多个 ActionX 形式的接口 (例如 Action2, Action3) 的,
439 | * 它们可以被用以包装不同的无返回值的方法。
440 | */
441 |
442 |
443 | //---------------------------------------5: 休息一下!推荐两个好用的日志查看工具-------------------------------------------------------------
444 |
445 | //1.[logger](https://github.com/orhanobut/logger) | 一个简洁,优雅,功能强大的Android日志输出工具
446 | //2.[pidcat](https://github.com/JakeWharton/pidcat)|JakeWharton项目一个简洁,优雅的,彩色日志终端查看库|在终端过滤日志信息
447 |
448 | /**
449 | * 使用com.github.orhanobut:logger 库可以查看当前的线程
450 | * ╔════════════════════════════════════════════════════════════════════════════════════════
451 | D ║ Thread: main
452 | D ╟────────────────────────────────────────────────────────────────────────────────────────
453 | D ║ MainActivity$11.onNext (MainActivity.java:338)
454 | D ║ MainActivity$11.onNext (MainActivity.java:354)
455 | D ╟────────────────────────────────────────────────────────────────────────────────────────
456 | D ║ 观察者 onNext()
457 | D ╚════════════════════════════════════════════════════════════════════════════════════════
458 | D ╔════════════════════════════════════════════════════════════════════════════════════════
459 | D ║ Thread: main
460 | D ╟────────────────────────────────────────────────────────────────────────────────────────
461 | D ║ SafeSubscriber.onCompleted (SafeSubscriber.java:83)
462 | D ║ MainActivity$11.onCompleted (MainActivity.java:341)
463 | D ╟────────────────────────────────────────────────────────────────────────────────────────
464 | D ║ 观察者 onCompleted()
465 | D ╚════════════════════════════════════════════════════════════════════════════════════════
466 | */
467 |
468 | //---------------------------------------6 线程控制-Scheduler-------------------------------------------------------------
469 |
470 | /**
471 | * 显示图片
472 | * 后台线程取数据,主线程显示
473 | * 加载图片将会发生在 IO 线程,而设置图片则被设定在了主线程。这就意味着,即使加载图片耗费了几十甚至几百毫秒的时间,也不会造成丝毫界面的卡顿。
474 | */
475 | private void method6() {
476 |
477 | final int drawableRes = R.mipmap.malin;
478 | Observable.create(new Observable.OnSubscribe() { //1:被观察者
479 | @Override
480 | public void call(Subscriber super Drawable> subscriber) {
481 | Logger.d("被观察者");
482 | Drawable drawable = ContextCompat.getDrawable(RxJavaApplication.getApplication(), drawableRes);
483 | subscriber.onNext(drawable);
484 | subscriber.onCompleted();
485 | }
486 | })
487 | .subscribeOn(Schedulers.io())//事件产生的线程。指定 subscribe() 发生在 IO 线程
488 | // doOnSubscribe() 之后有 observeOn() 的话,它将执行在离它最近的 observeOn() 所指定的线程。这里将执行在主线程中
489 | .doOnSubscribe(new Action0() {
490 | @Override
491 | public void call() {
492 | if (mProgressBar != null) {
493 | mProgressBar.setVisibility(View.VISIBLE);//显示一个等待的ProgressBar--需要在主线程中执行
494 | }
495 | }
496 | })
497 | .observeOn(AndroidSchedulers.mainThread())//指定 Subscriber 所运行在的线程。或者叫做事件消费的线程
498 | .subscribe(new Subscriber() { //3:订阅 //2:观察者
499 | @Override
500 | public void onCompleted() {
501 | if (mProgressBar != null) {
502 | mProgressBar.setVisibility(View.GONE);
503 | }
504 | Logger.d("观察者 onCompleted()");
505 | Toast.makeText(MainActivity.this, "观察者 onCompleted()", Toast.LENGTH_SHORT).show();
506 | }
507 |
508 | @Override
509 | public void onError(Throwable e) {
510 | if (mProgressBar != null) {
511 | mProgressBar.setVisibility(View.GONE);
512 | }
513 | Logger.d("观察者 onError()");
514 | Toast.makeText(MainActivity.this, "观察者 onError() " + e.getMessage(), Toast.LENGTH_SHORT).show();
515 |
516 | }
517 |
518 | @Override
519 | public void onNext(Drawable drawable) {
520 | Toast.makeText(MainActivity.this, "观察者 onNext()", Toast.LENGTH_SHORT).show();
521 | Logger.d("观察者 onNext()");
522 | if (mImageView == null || drawable == null) return;
523 | mImageView.setImageDrawable(drawable);
524 | }
525 | });
526 |
527 | }
528 |
529 | //---------------------------------------7: 变换 map()-------------------------------------------------------------
530 | private void method7() {
531 | final int drawableRes = R.mipmap.malin;
532 |
533 | //1:被观察者
534 | Observable.just(drawableRes)//输入类型 int
535 | .map(new Func1() {
536 |
537 | @Override
538 | public Drawable call(Integer integer) {// 参数类型 String
539 | Logger.d("integer:" + integer);
540 | return ContextCompat.getDrawable(RxJavaApplication.getApplication(), integer);
541 | }
542 | })
543 | .subscribeOn(Schedulers.io())//事件产生的线程。指定 subscribe() 发生在 IO 线程
544 | //doOnSubscribe() 之后有 observeOn() 的话,它将执行在离它最近的 observeOn() 所指定的线程。这里将执行在主线程中
545 | .doOnSubscribe(new Action0() {
546 | @Override
547 | public void call() {
548 | if (mProgressBar != null) {
549 | mProgressBar.setVisibility(View.VISIBLE);//显示一个等待的ProgressBar--需要在主线程中执行
550 | }
551 | }
552 | })
553 | .observeOn(AndroidSchedulers.mainThread())//指定 Subscriber 所运行在的线程。或者叫做事件消费的线程
554 | .subscribe(new Subscriber() { //3:订阅 //2:观察者
555 | @Override
556 | public void onCompleted() {
557 | if (mProgressBar != null) {
558 | mProgressBar.setVisibility(View.GONE);
559 | }
560 | Logger.d("观察者:onCompleted()");
561 | }
562 |
563 | @Override
564 | public void onError(Throwable e) {
565 | if (mProgressBar != null) {
566 | mProgressBar.setVisibility(View.GONE);
567 | }
568 | Toast.makeText(MainActivity.this, "" + e.getMessage(), Toast.LENGTH_SHORT).show();
569 | Logger.d("观察者:onError(Throwable e):" + e.getMessage());
570 | }
571 |
572 | @Override
573 | public void onNext(Drawable drawable) {
574 | if (mImageView == null || drawable == null) return;
575 | mImageView.setImageDrawable(drawable);
576 | Logger.d("观察者:onNext(Drawable drawable):" + drawable.toString());
577 | }
578 | });
579 | }
580 |
581 | //---------------------------------------8: 练习 中途休息一下-------------------------------------------------------------
582 |
583 | //演示嵌套循环
584 | private void method8() {
585 | ArrayList students = DataFactory.getData();
586 | int size = students.size();
587 | for (int i = 0; i < size; i++) {
588 | Logger.d("姓名:" + students.get(i).name);
589 | int sizeCourses = students.get(i).courses.size();
590 | for (int j = 0; j < sizeCourses; j++) {
591 | Logger.d("课程:" + students.get(i).courses.get(j).name);
592 | }
593 | }
594 | }
595 |
596 |
597 | /**
598 | * 需要:依次输入学生的姓名:将每个学生(实体对象)依次发射出去
599 | * RxJava解决方案:
600 | * {@link #method8()}
601 | */
602 | private void method9() {
603 | //just(T...): 将传入的参数依次发送出来,实现遍历的目的
604 | Observable.from(DataFactory.getData())
605 | .subscribeOn(Schedulers.io())
606 | .observeOn(AndroidSchedulers.mainThread())
607 | .subscribe(new Action1() {
608 | @Override
609 | public void call(Student student) {
610 | Logger.d("观察者:" + student.name);
611 | }
612 | });
613 | }
614 |
615 |
616 | /**
617 | * 需要:输出学生的姓名:将每个学生的(姓名)依次发射出去
618 | * RxJava解决方案
619 | * {@link #method9()}
620 | */
621 | private void method10() {
622 |
623 | //1:被观察者
624 |
625 | //2:数据转换
626 |
627 | //3:事件产生的线程。
628 |
629 | //4:事件消费的线程。
630 |
631 | //5:被观察者被观察者订阅
632 |
633 | //6:观察者
634 |
635 | Observable.from(DataFactory.getData())
636 |
637 | .map(new Func1() {
638 | @Override
639 | public String call(Student student) {
640 | return student.name;
641 | }
642 | })
643 | .subscribeOn(Schedulers.io())
644 | .observeOn(AndroidSchedulers.mainThread())
645 | .subscribe(new Subscriber() {
646 | @Override
647 | public void onCompleted() {
648 | Logger.d("观察者:onCompleted()");
649 | }
650 |
651 | @Override
652 | public void onError(Throwable e) {
653 | Logger.d("观察者:onError(Throwable e) " + e.getMessage());
654 | }
655 |
656 | @Override
657 | public void onNext(String s) {
658 | Logger.d("观察者:onNext(String s) " + s);
659 | }
660 | });
661 |
662 | }
663 |
664 | /**
665 | * 需要:输出学生的姓名:将每个学生的(姓名)依次发射出去,对method9()的简化
666 | * RxJava解决方案
667 | * 输出学生的姓名
668 | * {@link #method10()}
669 | */
670 | private void method11() {
671 | Observable.from(DataFactory.getData())
672 | .map(new Func1() {
673 | @Override
674 | public String call(Student student) {
675 | return student.name;
676 | }
677 | })
678 | .subscribeOn(Schedulers.io())
679 | .observeOn(AndroidSchedulers.mainThread())
680 | .subscribe(new Action1() {
681 | @Override
682 | public void call(String s) {
683 | Logger.d("观察者:" + s);
684 | }
685 | });
686 |
687 | }
688 |
689 | //---------------------------------------9: 引入flatmap()-------------------------------------------------------------
690 |
691 | /**
692 | * 需要:输出每一个学生所有选修的课程
693 | * 嵌套循环的RxJava解决方案
694 | * 输出每一个学生选修的课程
695 | * {@link #method11()}
696 | */
697 | private void method12() {
698 |
699 | //1:被观察者
700 |
701 | //2:被观察者被观察者订阅
702 |
703 | //3:观察者
704 |
705 | Observable.from(DataFactory.getData())
706 | .subscribe(new Subscriber() {
707 | @Override
708 | public void onCompleted() {
709 | Logger.d("观察者:onCompleted()");
710 | }
711 |
712 | @Override
713 | public void onError(Throwable e) {
714 | Logger.d("观察者:onError(Throwable e)" + e.getMessage());
715 | }
716 |
717 | @Override
718 | public void onNext(Student student) {
719 | ArrayList courses = student.courses;
720 | for (Course course : courses) {
721 | Logger.d("观察者:" + course.name);
722 | }
723 | }
724 | });
725 |
726 | }
727 |
728 | /**
729 | * 需要:输出每一个学生选修的课程,对method12的简化
730 | * 嵌套循环的RxJava解决方案
731 | * {@link #method12()}
732 | * Student->ArrayList
733 | */
734 | private void method13() {
735 |
736 | Observable.from(DataFactory.getData())
737 |
738 | .map(new Func1>() {
739 | @Override
740 | public ArrayList call(Student student) {
741 | return student.courses;
742 | }
743 | }).subscribeOn(Schedulers.io())
744 | .observeOn(AndroidSchedulers.mainThread())
745 | .subscribe(new Action1>() {
746 | @Override
747 | public void call(ArrayList courses) {
748 | for (int i = 0; i < courses.size(); i++) {
749 | Logger.d("观察者:" + courses.get(i).name);
750 | }
751 | }
752 | });
753 | }
754 |
755 | //---------------------------------------10: flatMap()的使用-------------------------------------------------------------
756 |
757 | /**
758 | * 需要:输出每一个学生选修的课程,对method13的简化
759 | * 嵌套循环的RxJava解决方案
760 | * {@link #method13()}
761 | * Student -> ArrayList -> Observable ->
762 | */
763 | private void method14() {
764 |
765 | //1:被观察者
766 |
767 | //2:数据转换
768 |
769 | //3:事件产生的线程。
770 |
771 | //4:事件消费的线程。
772 |
773 | //5:被观察者被观察者订阅
774 |
775 | //6:观察者
776 |
777 | // Student->Course
778 | Observable.from(DataFactory.getData())
779 | .flatMap(new Func1>() {
780 | @Override
781 | public Observable call(Student student) {
782 | return Observable.from(student.courses);
783 | }
784 | }).subscribeOn(Schedulers.io())
785 | .observeOn(AndroidSchedulers.mainThread())
786 | .subscribe(new Action1() {
787 | @Override
788 | public void call(Course course) {
789 | Logger.d("观察者:" + course.name);
790 | }
791 | });
792 | }
793 |
794 |
795 | //---------------------------------------10: RxBinding的引入-------------------------------------------------------------
796 |
797 |
798 | /**
799 | * 需要防止快速连续点击,短时间内连续点击.
800 | */
801 | private void method15() {
802 |
803 |
804 | mImageView.setOnClickListener(new View.OnClickListener() {
805 | @Override
806 | public void onClick(View v) {
807 | runOnUiThread(new Runnable() {
808 | @Override
809 | public void run() {
810 | if (ClickUtils.isFastDoubleClick()) {
811 | ToastUtil.getInstance().showToast(MainActivity.this, "点击过快啦");
812 | return;
813 | }
814 | ToastUtil.getInstance().showToast(MainActivity.this, "匿名内部类实现click");
815 | }
816 | });
817 | }
818 | });
819 |
820 |
821 | }
822 |
823 | /**
824 | * RxBinding
825 | * RxBinding 是 Jake Wharton 的一个开源库,它提供了一套在 Android 平台上的基于 RxJava 的 Binding API。
826 | * 所谓 Binding,就是类似设置 OnClickListener 、设置 TextWatcher 这样的注册绑定对象的 API。
827 | * 举个设置点击监听的例子。使用 RxBinding ,可以把事件监听用这样的方法来设置:
828 | * throttleFirst() ,用于去抖动,也就是消除手抖导致的快速连环点击:
829 | */
830 | private void method16() {
831 | RxView.clicks(mImageView)
832 | .throttleFirst(500, TimeUnit.MILLISECONDS)//500ms,第一次点击后,500ms内点击无效,500ms后点击才会响应
833 | .subscribeOn(AndroidSchedulers.mainThread())
834 | .observeOn(AndroidSchedulers.mainThread())
835 | .subscribe(new Action1() {
836 | @Override
837 | public void call(Void aVoid) {
838 | Toast.makeText(MainActivity.this, "click", Toast.LENGTH_SHORT).show();
839 | }
840 | });
841 | }
842 |
843 | /**
844 | * RxBinding
845 | */
846 | private void method17() {
847 | RxView.longClicks(mImageView)
848 | .throttleFirst(500, TimeUnit.MILLISECONDS)
849 | .subscribe(new Action1() {
850 | @Override
851 | public void call(Void aVoid) {
852 | Toast.makeText(MainActivity.this, "long click", Toast.LENGTH_SHORT).show();
853 | }
854 | });
855 | }
856 |
857 | /**
858 | * EditText,每隔500ms,去响应变化
859 | */
860 | private void method18() {
861 | mSearchEditText.setVisibility(View.VISIBLE);
862 | RxTextView.textChangeEvents(mSearchEditText)
863 | .debounce(500, TimeUnit.MILLISECONDS)
864 | .observeOn(AndroidSchedulers.mainThread())
865 | .subscribe(new Subscriber() {
866 | @Override
867 | public void onCompleted() {
868 | }
869 |
870 | @Override
871 | public void onError(Throwable e) {
872 | }
873 |
874 | @Override
875 | public void onNext(TextViewTextChangeEvent textViewTextChangeEvent) {
876 | String changedMessage = textViewTextChangeEvent.text().toString();
877 | Logger.d(TAG, changedMessage);
878 | if (!TextUtils.isEmpty(changedMessage)) {
879 | ToastUtil.getInstance().showToast(MainActivity.this, changedMessage);
880 | }
881 | }
882 | });
883 | }
884 |
885 | /**
886 | * 三、Defer、Just
887 | */
888 | //操作符号 Range操作符根据出入的初始值n和数目m发射一系列大于等于n的m个值
889 | //例如:实现:输出1,2,3,4,5
890 | // 其使用也非常方便,仅仅制定初始值和数目就可以了,不用自己去实现对Subscriber的调用
891 | private void method19() {
892 | Observable.range(1, 5)
893 | .subscribeOn(Schedulers.io())
894 | .observeOn(AndroidSchedulers.mainThread())
895 | .subscribe(new Action1() {
896 | @Override
897 | public void call(Integer integer) {
898 | Logger.d(integer.toString() + "");
899 | }
900 | });
901 | }
902 |
903 | /**
904 | * 使用Retrofit网络库,获取androidmalin的GitHub个人信息
905 | */
906 | private void method21() {
907 |
908 | mProgressBar.setVisibility(View.VISIBLE);
909 | mImageView.setVisibility(View.GONE);
910 | mResultTextView.setVisibility(View.VISIBLE);
911 | mResultTextView.setText("");
912 | Call call = RetrofitService.getInstance().createService(GitHubApi.class).getUser("androidmalin");
913 |
914 | //asynchronous
915 | call.enqueue(new Callback() {
916 | @Override
917 | public void onResponse(Call call, Response response) {
918 | User user = (User) response.body();
919 |
920 | if (user == null) {
921 | //404 or the response cannot be converted to User.
922 | ResponseBody responseBody = response.errorBody();
923 | if (responseBody != null) {
924 | try {
925 | Logger.d("responseBody = " + responseBody.string());
926 | mResultTextView.setText("responseBody = " + responseBody.string());
927 | } catch (IOException e) {
928 | e.printStackTrace();
929 | }
930 | } else {
931 | Logger.d("responseBody = null");
932 | mResultTextView.setText("responseBody = null");
933 | }
934 | } else {
935 | //200
936 | String message = "Github Name :" + user.name + "\nWebsite :" + user.blog + "\nCompany Name :" + user.company;
937 | ToastUtil.getInstance().showToast(MainActivity.this, message);
938 | Logger.d(message);
939 | mResultTextView.setText(message);
940 | }
941 | mProgressBar.setVisibility(View.GONE);
942 | }
943 |
944 | @Override
945 | public void onFailure(Call call, Throwable t) {
946 | Logger.d("t = " + t.getMessage());
947 | mProgressBar.setVisibility(View.GONE);
948 | }
949 | });
950 | }
951 |
952 | /**
953 | * 使用Retrofit网络库,同时使用RxJava 获取androidmalin的GitHub个人信息
954 | */
955 | private void method22() {
956 | //TODO:1:被观察者,数据源
957 | //TODO:2:观察者
958 | //TODO:3:订阅,被观察者 被 观察者订阅
959 |
960 | Observable observable = RetrofitService.getInstance().createService(GitHubApi.class).getUserObservable("androidmalin");
961 | observable
962 | .subscribeOn(Schedulers.io())
963 | .doOnSubscribe(new Action0() {
964 | @Override
965 | public void call() {
966 | mProgressBar.setVisibility(View.VISIBLE);
967 | mResultTextView.setText("");
968 | mImageView.setVisibility(View.GONE);
969 | mResultTextView.setVisibility(View.VISIBLE);
970 | }
971 | })
972 | .observeOn(AndroidSchedulers.mainThread())
973 | .subscribe(new Subscriber() {
974 | @Override
975 | public void onCompleted() {
976 | Logger.d("onCompleted()");
977 | mProgressBar.setVisibility(View.INVISIBLE);
978 | Toast.makeText(MainActivity.this, "onCompleted", Toast.LENGTH_SHORT).show();
979 | }
980 |
981 | @Override
982 | public void onError(Throwable e) {
983 | Logger.d("onError()=>" + e.getMessage());
984 | }
985 |
986 | @Override
987 | public void onNext(User user) {
988 | Logger.d("onNext()");
989 | String message = "Github Name :" + user.name + "\nWebsite :" + user.blog + "\nCompany Name :" + user.company;
990 | Toast.makeText(MainActivity.this, "onNext", Toast.LENGTH_SHORT).show();
991 | Logger.d(message);
992 | mResultTextView.setText(user.toString());
993 | }
994 | });
995 | }
996 |
997 |
998 | private ArrayAdapter mAdapter;
999 | private CompositeSubscription mSubscription = new CompositeSubscription();
1000 | private ListView mResultListView;
1001 |
1002 |
1003 | /**
1004 | * 使用Retrofit网络库,同时使用RxJava 获取square的公司的retrofit项目的贡献者
1005 | */
1006 | private void method23() {
1007 |
1008 | mImageView.setVisibility(View.GONE);
1009 | mResultTextView.setVisibility(View.GONE);
1010 | mImageView.setVisibility(View.GONE);
1011 |
1012 | mResultListView = (ListView) findViewById(R.id.lv_list);
1013 | mAdapter = new ArrayAdapter(MainActivity.this, R.layout.item_log, R.id.item_log, new ArrayList());
1014 | mResultListView.setAdapter(mAdapter);
1015 |
1016 | mSubscription.add(RetrofitService.getInstance().createService(GitHubApi.class).getContributorsObservable("square", "retrofit")
1017 | .subscribeOn(Schedulers.io())
1018 | .observeOn(AndroidSchedulers.mainThread())
1019 | .doOnSubscribe(new Action0() {
1020 | @Override
1021 | public void call() {
1022 | mProgressBar.setVisibility(View.VISIBLE);
1023 | }
1024 | })
1025 | .subscribe(new Observer>() {
1026 | @Override
1027 | public void onCompleted() {
1028 | Logger.d("Retrofit call 1 completed");
1029 | mProgressBar.setVisibility(View.GONE);
1030 | mResultListView.setVisibility(View.VISIBLE);
1031 | ToastUtil.getInstance().showToast(MainActivity.this, "onCompleted");
1032 | }
1033 |
1034 | @Override
1035 | public void onError(Throwable e) {
1036 | mProgressBar.setVisibility(View.GONE);
1037 | Logger.e(e.getMessage() + " woops we got an error while getting the list of contributors");
1038 | ToastUtil.getInstance().showToast(MainActivity.this, "onError");
1039 | }
1040 |
1041 | @Override
1042 | public void onNext(List contributors) {
1043 | ToastUtil.getInstance().showToast(MainActivity.this, "onNext");
1044 | for (Contributor c : contributors) {
1045 | mAdapter.add(String.format("%s has made %d contributions to %s",
1046 | c.login,
1047 | c.contributions,
1048 | "retrofit"));
1049 |
1050 | Logger.d(String.format("%s has made %d contributions to %s",
1051 | c.login,
1052 | c.contributions,
1053 | "retrofit"));
1054 | }
1055 | }
1056 | }));
1057 | }
1058 |
1059 |
1060 | private static final int COUNT = 10;
1061 | private static final int TIME_ALL = 5000;
1062 | private ArrayList timeList = new ArrayList<>();
1063 |
1064 | private void method20() {
1065 |
1066 | final int COUNT = 5;
1067 | final int TIME_ALL = 3000;
1068 | final ArrayList timeList = new ArrayList<>();
1069 | final ArrayList allList = new ArrayList<>();
1070 |
1071 | RxView.clicks(findViewById(R.id.iv_image))
1072 | .map(new Func1() {
1073 | @Override
1074 | public Long call(Void aVoid) {
1075 | return System.currentTimeMillis();
1076 | }
1077 | })
1078 | .map(new Func1() {
1079 | @Override
1080 | public Boolean call(Long nowTime) {
1081 | allList.add(nowTime);
1082 | timeList.add(nowTime);
1083 |
1084 | boolean isOver = false;
1085 | Log.d(TAG, "timeList.size():" + timeList.size());
1086 | if (timeList.size() >= COUNT) {
1087 |
1088 | if (nowTime - timeList.get(0) < TIME_ALL) {
1089 | isOver = true;
1090 | } else {
1091 | isOver = false;
1092 | }
1093 | timeList.clear();
1094 | }
1095 | return isOver;
1096 | }
1097 | }).subscribe(new Action1() {
1098 | @Override
1099 | public void call(Boolean aBoolean) {
1100 | if (aBoolean) {
1101 | Toast.makeText(MainActivity.this, "3秒内点击超过了" + allList.size(), Toast.LENGTH_SHORT).show();
1102 | allList.clear();
1103 | } else {
1104 | // Toast.makeText(MainActivity.this, "ok "+timeList.size(), Toast.LENGTH_SHORT).show();
1105 | }
1106 | }
1107 | });
1108 | }
1109 |
1110 | public static String timeLongToString(long data) {
1111 | Date date = new Date(data);
1112 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
1113 | return formatter.format(date);
1114 | }
1115 |
1116 |
1117 | private void log(final String str) {
1118 | runOnUiThread(new Runnable() {
1119 | @Override
1120 | public void run() {
1121 | Log.d(TAG, str);
1122 | }
1123 | });
1124 | }
1125 |
1126 | /**
1127 | * 测试这些每个知识点的功能
1128 | *
1129 | * @param number
1130 | */
1131 | private void testFuncation(int number) {
1132 | switch (number) {
1133 | case 0: {
1134 | method0();
1135 | break;
1136 | }
1137 |
1138 | case 1: {
1139 | method1();
1140 | break;
1141 | }
1142 |
1143 | case 2: {
1144 | method2();
1145 | break;
1146 | }
1147 |
1148 | case 3: {
1149 | method3();
1150 | break;
1151 | }
1152 |
1153 | case 4: {
1154 | method4();
1155 | break;
1156 | }
1157 |
1158 | case 5: {
1159 | method5();
1160 | break;
1161 | }
1162 |
1163 | case 6: {
1164 | method6();
1165 | break;
1166 | }
1167 |
1168 | case 7: {
1169 | method7();
1170 | break;
1171 | }
1172 |
1173 | case 8: {
1174 | method8();
1175 | break;
1176 | }
1177 |
1178 | case 9: {
1179 | method9();
1180 | break;
1181 | }
1182 |
1183 | case 10: {
1184 | method10();
1185 | break;
1186 | }
1187 |
1188 | case 11: {
1189 | method11();
1190 | break;
1191 | }
1192 |
1193 | case 12: {
1194 | method12();
1195 | break;
1196 | }
1197 |
1198 | case 13: {
1199 | method13();
1200 | break;
1201 | }
1202 |
1203 | case 14: {
1204 | method14();
1205 | break;
1206 | }
1207 |
1208 | case 15: {
1209 | method15();
1210 | break;
1211 | }
1212 | case 16: {
1213 | method16();
1214 | break;
1215 | }
1216 |
1217 | case 17: {
1218 | method17();
1219 | break;
1220 | }
1221 |
1222 | case 18: {
1223 | method18();
1224 | break;
1225 | }
1226 |
1227 |
1228 | case 19: {
1229 | method19();
1230 | break;
1231 | }
1232 |
1233 | case 20: {
1234 | method20();
1235 | break;
1236 | }
1237 |
1238 | case 21: {
1239 | method21();
1240 | break;
1241 | }
1242 |
1243 |
1244 | case 22: {
1245 | method22();
1246 | break;
1247 | }
1248 |
1249 | case 23: {
1250 | method23();
1251 | break;
1252 | }
1253 | default: {
1254 |
1255 | break;
1256 | }
1257 | }
1258 | }
1259 |
1260 |
1261 | @Override
1262 | public void onResume() {
1263 | super.onResume();
1264 | mSubscription = RxUtils.getNewCompositeSubIfUnsubscribed(mSubscription);
1265 | }
1266 |
1267 | @Override
1268 | public void onPause() {
1269 | super.onPause();
1270 |
1271 | RxUtils.unsubscribeIfNotNull(mSubscription);
1272 | }
1273 |
1274 | private boolean mGoToRecycleImageView = false;
1275 |
1276 | @Override
1277 | protected void onDestroy() {
1278 | super.onDestroy();
1279 | //rl_root_layout 这个是根布局的id
1280 | unBingListener(findViewById(R.id.rl_root_layout));
1281 | unBindDrawables(findViewById(R.id.rl_root_layout));
1282 | recycleImageView();
1283 | }
1284 |
1285 |
1286 | private void recycleImageView() {
1287 | //回收ImageView占用的图像内存
1288 | if (mGoToRecycleImageView) {
1289 | Logger.d("onDestroy()> RecycleBitmap.recycleImageView(mImageView)");
1290 | RecycleBitmap.recycleImageView(mImageView);
1291 | mImageView.setImageBitmap(null);
1292 | }
1293 |
1294 | if (mManyBitmapSuperposition != null && !mManyBitmapSuperposition.isRecycled()) {
1295 | mManyBitmapSuperposition.recycle();
1296 | mManyBitmapSuperposition = null;
1297 | }
1298 |
1299 | //@link http://blog.csdn.net/yanzi1225627/article/details/8236309
1300 | if (mCanvas != null) {
1301 | //清屏
1302 | Paint paint = new Paint();
1303 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
1304 | mCanvas.drawPaint(paint);
1305 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
1306 | mCanvas = null;
1307 | }
1308 |
1309 | }
1310 |
1311 | /**
1312 | * 做法也非常简单,在Activity onDestory时候从view的rootview开始,
1313 | * 递归释放所有子view涉及的图片,背景,DrawingCache,监听器等等资源,
1314 | * 让Activity成为一个不占资源的空壳,泄露了也不会导致图片资源被持有。
1315 | *
1316 | * @param view:the root view of the layout
1317 | * @description Unbind the rootView
1318 | * @author malin.myemail@gmail.com
1319 | * @link http://stackoverflow.com/questions/9461364/exception-in-unbinddrawables
1320 | * http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=400656149&idx=1&sn=122b4f4965fafebf78ec0b4fce2ef62a&3rd=MzA3MDU4NTYzMw==&scene=6#rd
1321 | * @since 2015.12.16
1322 | */
1323 | private void unBindDrawables(View view) {
1324 | if (view != null) {
1325 | try {
1326 | Drawable drawable = view.getBackground();
1327 | if (drawable != null) {
1328 | drawable.setCallback(null);
1329 | } else {
1330 | }
1331 | if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
1332 | ViewGroup viewGroup = (ViewGroup) view;
1333 | int viewGroupChildCount = viewGroup.getChildCount();
1334 | for (int j = 0; j < viewGroupChildCount; j++) {
1335 | unBindDrawables(viewGroup.getChildAt(j));
1336 | }
1337 | viewGroup.removeAllViews();
1338 | }
1339 | } catch (Exception e) {
1340 | e.printStackTrace();
1341 | }
1342 |
1343 | }
1344 | }
1345 |
1346 | /**
1347 | * Remove an onclick listener
1348 | *
1349 | * @param view
1350 | * @author malin.myemail@gmail.com
1351 | * @website https://github.com/androidmalin
1352 | * @data 2016/01/22
1353 | */
1354 | private void unBingListener(View view) {
1355 | if (view != null) {
1356 | try {
1357 | if (view.hasOnClickListeners()) {
1358 | view.setOnClickListener(null);
1359 | }
1360 | if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
1361 | ViewGroup viewGroup = (ViewGroup) view;
1362 | int viewGroupChildCount = viewGroup.getChildCount();
1363 | for (int i = 0; i < viewGroupChildCount; i++) {
1364 | unBingListener(viewGroup.getChildAt(i));
1365 | }
1366 | }
1367 | } catch (Exception e) {
1368 | e.printStackTrace();
1369 | }
1370 |
1371 | }
1372 | }
1373 |
1374 | //-----------------------------------谜之缩进--嵌套循环--回调地狱 -----------------------------------------------------------
1375 |
1376 | /**
1377 | * 实现的功能:获取assets文件夹下所有文件夹中的jpg图片,并且将所有的图片画到一个ImageView上,没有实际的用处,只是为了说明问题--- 谜之缩进--嵌套循环--回调地狱
1378 | * 不使用RxJava的写法-- 谜之缩进--回调地狱
1379 | */
1380 | //思路:需要以下6个步骤完成
1381 | //1:遍历获取assets文件夹下所有的文件夹的名称
1382 | //2:遍历获取获取assets文件夹下某个文件夹中所有图片路径的集合
1383 | //3:过滤掉非JPG格式的图片
1384 | //4:获取某个路径下图片的bitmap
1385 | //5:将Bitmap绘制到画布上
1386 | //6:循环结束后更新UI,给ImageView设置最后绘制完成后的Bitmap,隐藏ProgressBar
1387 | private void miZhiSuoJinAndNestedLoopAndCallbackHell() {
1388 | new Thread(new Runnable() {
1389 | @Override
1390 | public void run() {
1391 |
1392 | runOnUiThread(new Runnable() {
1393 | @Override
1394 | public void run() {
1395 | mProgressBar.setVisibility(View.VISIBLE);
1396 | }
1397 | });
1398 | //1:遍历获取assets文件夹下所有的文件夹的名称
1399 | ArrayList assetsFolderNameList = ImageNameFactory.getAssetImageFolderName();
1400 |
1401 | for (String folderName : assetsFolderNameList) {
1402 |
1403 | //2:遍历获取获取assets文件夹下某个文件夹中所有图片路径的集合
1404 | ArrayList imagePathList = ImageUtils.getAssetsImageNamePathList(getApplicationContext(), folderName);
1405 |
1406 | for (final String imagePathName : imagePathList) {
1407 | //3:过滤掉非JPG格式的图片
1408 | if (imagePathName.endsWith(JPG)) {
1409 |
1410 | //4:获取某个路径下图片的bitmap
1411 | final Bitmap bitmap = ImageUtils.getImageBitmapFromAssetsFolderThroughImagePathName(getApplicationContext(), imagePathName, Constant.IMAGE_WITH, Constant.IMAGE_HEIGHT);
1412 | runOnUiThread(new Runnable() {
1413 | @Override
1414 | public void run() {
1415 | //Logger.d(mCounter + ":" + imagePathName);
1416 |
1417 | //5:将Bitmap绘制到画布上
1418 | createSingleImageFromMultipleImages(bitmap, mCounter);
1419 | mCounter++;
1420 |
1421 | }
1422 | });
1423 | }
1424 | }
1425 | }
1426 |
1427 |
1428 | //6:循环结束后更新UI,给ImageView设置最后绘制完成后的Bitmap,隐藏ProgressBar
1429 | runOnUiThread(new Runnable() {
1430 | @Override
1431 | public void run() {
1432 | mImageView.setImageBitmap(mManyBitmapSuperposition);
1433 | mProgressBar.setVisibility(View.GONE);
1434 | }
1435 | });
1436 |
1437 | }
1438 | }).start();
1439 | }
1440 |
1441 |
1442 | /**
1443 | * 就是循环在画布上画图,呈现一种整齐的线性分布:像方格
1444 | * 所有绘制都绘制到了创建Canvas时传入的Bitmap上面
1445 | *
1446 | * @param bitmap:每张图片对应的Bitamp
1447 | * @param mCounter:一个自增的整数从0开始
1448 | */
1449 | //实现思路:
1450 | //1:产生和手机屏幕尺寸同样大小的Bitmap
1451 | //2:以Bitmap对象创建一个画布,将内容都绘制在Bitmap上,这个Bitmap用来存储所有绘制在Canvas上的像素信息.
1452 | //3:这里将所有图片压缩成了相同的尺寸均为正方形图(64px*64px)
1453 | //4:计算获取绘制每个Bitmap的坐标,距离屏幕左边和上边的距离,距离左边的距离不断自增,距离顶部的距离循环自增
1454 | //5:将Bitmap画到指定坐标
1455 | private void createSingleImageFromMultipleImages(Bitmap bitmap, int mCounter) {
1456 | if (mCounter == 0) {
1457 | //1:产生和手机屏幕尺寸同样大小的Bitmap
1458 | mManyBitmapSuperposition = Bitmap.createBitmap(DeviceInfo.screenWidthForPortrait, DeviceInfo.screenHeightForPortrait, bitmap.getConfig());
1459 |
1460 | //2:以Bitmap对象创建一个画布,则将内容都绘制在Bitmap上
1461 | mCanvas = new Canvas(mManyBitmapSuperposition);
1462 | }
1463 | if (mCanvas != null) {
1464 | int left;//距离左边的距离
1465 | int top;//距离顶部的距离
1466 |
1467 | //3:这里将所有图片压缩成了相同的尺寸均为正方形图(64px*64px)
1468 | int imageWidth = Constant.IMAGE_WITH;
1469 | int imageHeight = Constant.IMAGE_HEIGHT;
1470 | int number = DeviceInfo.screenHeightForPortrait / imageHeight;//手机竖屏模式下,垂直方向上绘制图片的个数
1471 |
1472 | //4:计算获取绘制每个Bitmap的坐标,距离屏幕左边和上边的距离,距离左边的距离不断自增,距离顶部的距离循环自增
1473 | if (mCounter >= (mCounter / number) * number && mCounter < (((mCounter / number) + 1) * number)) {//[0,number)
1474 | left = (mCounter / number) * imageWidth;
1475 | top = (mCounter % number) * imageHeight;
1476 | // Log.d(TAG,""+mCounter+" left="+left+" top="+top);
1477 |
1478 | //5:将Bitmap画到指定坐标
1479 | mCanvas.drawBitmap(bitmap, left, top, null);
1480 | }
1481 | }
1482 | }
1483 |
1484 |
1485 | /**
1486 | * 用于测试除法和取余
1487 | */
1488 | private void showMath() {
1489 | String TAG = "Math";
1490 | for (int i = 0; i < 100; i++) {
1491 | int ss = i / 10;
1492 | int ww = i % 10;
1493 | Log.d(TAG, i + "/10 ==" + ss);
1494 | Log.d(TAG, i + "%10 ==" + ww);
1495 | }
1496 | }
1497 |
1498 |
1499 | //-----------------------------------RxJava的实现--链式调用--十分简洁 -----------------------------------------------------------
1500 |
1501 |
1502 | private void rxJavaSolveMiZhiSuoJinAndNestedLoopAndCallbackHell() {
1503 | //1:被观察者:
1504 |
1505 | //2:数据转换
1506 |
1507 | //3:设置事件的产生发生在IO线程
1508 |
1509 | //4:设置事件的消费发生在主线程
1510 |
1511 | //5:观察者
1512 |
1513 | //6:订阅:被观察者被观察者订阅
1514 | mGoToRecycleImageView = false;
1515 | Observable.from(ImageNameFactory.getAssetImageFolderName())
1516 | //assets下一个文件夹的名称,assets下一个文件夹中一张图片的路径
1517 | .flatMap(new Func1>() {
1518 | @Override
1519 | public Observable call(String folderName) {
1520 | return Observable.from(ImageUtils.getAssetsImageNamePathList(getApplicationContext(), folderName));
1521 | }
1522 | })
1523 | //过滤,筛选出jpg图片
1524 | .filter(new Func1() {
1525 | @Override
1526 | public Boolean call(String imagePathNameAll) {
1527 | return imagePathNameAll.endsWith(JPG);
1528 | }
1529 | })
1530 | //将图片路径转换为对应图片的Bitmap
1531 | .map(new Func1() {
1532 | @Override
1533 | public Bitmap call(String imagePathName) {
1534 | return ImageUtils.getImageBitmapFromAssetsFolderThroughImagePathName(getApplicationContext(), imagePathName, Constant.IMAGE_WITH, Constant.IMAGE_HEIGHT);
1535 | }
1536 | })
1537 | .map(new Func1() {
1538 | @Override
1539 | public Void call(Bitmap bitmap) {
1540 | createSingleImageFromMultipleImages(bitmap, mCounter);
1541 | mCounter++;
1542 | return null;
1543 | }
1544 | })
1545 | .subscribeOn(Schedulers.io())//设置事件的产生发生在IO线程
1546 | .doOnSubscribe(new Action0() {
1547 | @Override
1548 | public void call() {
1549 | mProgressBar.setVisibility(View.VISIBLE);
1550 | }
1551 | })
1552 | .observeOn(AndroidSchedulers.mainThread())//设置事件的消费发生在主线程
1553 | .subscribe(new Subscriber() {
1554 | @Override
1555 | public void onCompleted() {
1556 | mImageView.setImageBitmap(mManyBitmapSuperposition);
1557 | mProgressBar.setVisibility(View.GONE);
1558 | }
1559 |
1560 | @Override
1561 | public void onError(Throwable e) {
1562 | //Toast.makeText(MainActivity.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
1563 | }
1564 |
1565 | @Override
1566 | public void onNext(Void aVoid) {
1567 |
1568 | }
1569 | });
1570 | }
1571 | }
1572 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/application/RxJavaApplication.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.application;
27 |
28 | import android.app.Application;
29 |
30 |
31 | /**
32 | * 类描述:Application
33 | * 创建人:malin.myemail@gmail.com
34 | * 创建时间:15-12-16 上午11:00
35 | * 修改人:
36 | * 修改时间:
37 | * 修改备注:
38 | */
39 | public class RxJavaApplication extends Application {
40 |
41 | private static RxJavaApplication application;
42 | @Override
43 | public void onCreate() {
44 | super.onCreate();
45 | application = this;
46 | }
47 |
48 | public static RxJavaApplication getApplication(){
49 | return application;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/constant/Constant.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.constant;
27 |
28 | /**
29 | * 类描述:全局常量
30 | * 创建人:malin.myemail@gmail.com
31 | * 创建时间:15-11-13.
32 | * 版本:1.0.0
33 | * 备注:
34 | */
35 | public class Constant {
36 | public static final int IMAGE_WITH = 64;//px
37 | public static final int IMAGE_HEIGHT = 64;//px
38 |
39 | public static final String BLANK_LOG = "\t";
40 | public static final boolean isDebug = true;
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/factory/DataFactory.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.factory;
27 |
28 | import com.malin.rxjava.model.Course;
29 | import com.malin.rxjava.model.Student;
30 |
31 | import java.util.ArrayList;
32 |
33 | /**
34 | * 类描述:获取学生集合
35 | * 创建人:malin.myemail@gmail.com
36 | * 创建时间:15-11-10.
37 | * 备注:
38 | */
39 | public class DataFactory {
40 |
41 | private DataFactory() {
42 | }
43 |
44 | /**
45 | * 获取学生集合
46 | *
47 | * [
48 | * 1:{
49 | * id:1
50 | * name:学生1
51 | * course:[学生1的课程1,学生1的课程2,学生1的课程3]
52 | * }
53 | *
54 | * 2:{
55 | * id:2
56 | * name:学生2
57 | * course:[学生2的课程1,学生2的课程2,学生2的课程3]
58 | * }
59 | *
60 | * 3:{
61 | * id:3
62 | * name:学生3
63 | * course:[学生3的课程1,学生3的课程2,学生3的课程3]
64 | * }
65 | * ]
66 | * @return
67 | */
68 | public static ArrayList getData() {
69 |
70 | ArrayList students = new ArrayList<>();
71 |
72 | ArrayList courses;
73 | Student student;
74 | Course course;
75 | for (int i = 0; i < 3; i++) {
76 |
77 | courses = new ArrayList<>();
78 |
79 | student = new Student();
80 | student.id = i;
81 | student.name = new StringBuffer("学生").append((i+1)).toString();
82 |
83 | for (int j = 0; j < 2; j++) {
84 | course = new Course();
85 | course.id = j;
86 | course.name = new StringBuffer(student.name).append("的课程").append((j+1)).toString();
87 | courses.add(course);
88 | }
89 |
90 | student.courses = courses;
91 | students.add(student);
92 |
93 |
94 | }
95 | return students;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/factory/ImageNameFactory.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.factory;
27 |
28 | import java.util.ArrayList;
29 |
30 | /**
31 | * 类描述:获取图片文件夹类
32 | * 创建人:malin.myemail@gmail.com
33 | * 创建时间:15-11-10.
34 | * 备注:
35 | */
36 | public class ImageNameFactory {
37 |
38 | private static final String FOLDER_NAME_ONE = "one";
39 | private static final String FOLDER_NAME_TWO = "two";
40 | private static final String FOLDER_NAME_THREE = "three";
41 | private static final String FOLDER_NAME_FOUR = "four";
42 |
43 | private ImageNameFactory() {
44 | }
45 |
46 | /**
47 | * 获取asset目录下的文件夹的名称集合
48 | *
49 | * @return
50 | */
51 | public static ArrayList getAssetImageFolderName() {
52 | ArrayList assetsFolderNameList = new ArrayList<>();
53 | assetsFolderNameList.add(FOLDER_NAME_ONE);
54 | assetsFolderNameList.add(FOLDER_NAME_TWO);
55 | assetsFolderNameList.add(FOLDER_NAME_THREE);
56 | assetsFolderNameList.add(FOLDER_NAME_FOUR);
57 | return assetsFolderNameList;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/githubapi/GitHubApi.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.githubapi;
27 |
28 |
29 | import com.malin.rxjava.model.Contributor;
30 | import com.malin.rxjava.model.User;
31 |
32 | import java.util.List;
33 |
34 | import retrofit2.Call;
35 | import retrofit2.http.GET;
36 | import retrofit2.http.Path;
37 | import rx.Observable;
38 |
39 | /**
40 | * 类描述:GitHubApi
41 | * 创建人:malin.myemail@gmail.com
42 | * 创建时间:16-1-24
43 | * 备注:https://github.com/basil2style
44 | */
45 | public interface GitHubApi {
46 |
47 | /**
48 | * See https://developer.github.com/v3/users/
49 | */
50 |
51 | @GET("/users/{username}")
52 | Call getUser(@Path("username") String user);
53 |
54 | @GET("/users/{username}")
55 | Observable getUserObservable(@Path("username") String username);
56 |
57 |
58 | /**
59 | * See https://developer.github.com/v3/repos/#list-contributors
60 | */
61 | @GET("/repos/{owner}/{repo}/contributors")
62 | Observable> getContributorsObservable(@Path("owner") String owner, @Path("repo") String repo);
63 |
64 | @GET("/repos/{owner}/{repo}/contributors")
65 | List getContributors(@Path("owner") String owner, @Path("repo") String repo);
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/model/Contributor.java:
--------------------------------------------------------------------------------
1 | package com.malin.rxjava.model;
2 |
3 | /**
4 | * 类描述::GitHub API 中的Contributor
5 | * 创建人:malin.myemail@gmail.com
6 | * 创建时间:16-1-24
7 | * 备注:https://github.com/kaushikgopal/RxJava-Android-Samples
8 | * 使用:http://www.jsonschema2pojo.org/这个网站就Json自动转换为POJO
9 | */
10 |
11 | public class Contributor {
12 | public String login;
13 | public Integer id;
14 | public String avatarUrl;
15 | public String gravatarId;
16 | public String url;
17 | public String htmlUrl;
18 | public String followersUrl;
19 | public String followingUrl;
20 | public String gistsUrl;
21 | public String starredUrl;
22 | public String subscriptionsUrl;
23 | public String organizationsUrl;
24 | public String reposUrl;
25 | public String eventsUrl;
26 | public String receivedEventsUrl;
27 | public String type;
28 | public Boolean siteAdmin;
29 | public Integer contributions;
30 |
31 | @Override
32 | public String toString() {
33 | return "Contributor{" +
34 | "login='" + login + '\'' +
35 | ", id=" + id +
36 | ", avatarUrl='" + avatarUrl + '\'' +
37 | ", gravatarId='" + gravatarId + '\'' +
38 | ", url='" + url + '\'' +
39 | ", htmlUrl='" + htmlUrl + '\'' +
40 | ", followersUrl='" + followersUrl + '\'' +
41 | ", followingUrl='" + followingUrl + '\'' +
42 | ", gistsUrl='" + gistsUrl + '\'' +
43 | ", starredUrl='" + starredUrl + '\'' +
44 | ", subscriptionsUrl='" + subscriptionsUrl + '\'' +
45 | ", organizationsUrl='" + organizationsUrl + '\'' +
46 | ", reposUrl='" + reposUrl + '\'' +
47 | ", eventsUrl='" + eventsUrl + '\'' +
48 | ", receivedEventsUrl='" + receivedEventsUrl + '\'' +
49 | ", type='" + type + '\'' +
50 | ", siteAdmin=" + siteAdmin +
51 | ", contributions=" + contributions +
52 | '}';
53 | }
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/model/Course.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.model;
27 |
28 | /**
29 | * 类描述:课程类
30 | * 创建人:malin.myemail@gmail.com
31 | * 创建时间:15-11-13.
32 | * 备注:
33 | */
34 |
35 | public class Course {
36 |
37 | public int id;//课程编号
38 | public String name;//课程名称
39 |
40 | @Override
41 | public String toString() {
42 | return "Course{" +
43 | "id=" + id +
44 | ", name='" + name + '\'' +
45 | '}';
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/model/Student.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.model;
27 |
28 | import java.util.ArrayList;
29 |
30 | /**
31 | * 类描述:学生类
32 | * 创建人:malin.myemail@gmail.com
33 | * 创建时间:15-11-10.
34 | * 备注:
35 | */
36 | public class Student {
37 |
38 | public int id;//学号
39 | public String name;//姓名
40 |
41 | public ArrayList courses;//学生选修的课程
42 |
43 | @Override
44 | public String toString() {
45 | return "Student{" +
46 | "id=" + id +
47 | ", name='" + name + '\'' +
48 | ", courses=" + courses +
49 | '}';
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/model/User.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.model;
27 |
28 | /**
29 | * 类描述:GitHub API 中的User
30 | * 创建人:malin.myemail@gmail.com
31 | * 创建时间:16-1-24
32 | * 备注:使用:http://www.jsonschema2pojo.org/这个网站就Json自动转换为POJO
33 | */
34 | public class User {
35 |
36 | public String login;
37 | public Integer id;
38 | public String avatarUrl;
39 | public String gravatarId;
40 | public String url;
41 | public String htmlUrl;
42 | public String followersUrl;
43 | public String followingUrl;
44 | public String gistsUrl;
45 | public String starredUrl;
46 | public String subscriptionsUrl;
47 | public String organizationsUrl;
48 | public String reposUrl;
49 | public String eventsUrl;
50 | public String receivedEventsUrl;
51 | public String type;
52 | public Boolean siteAdmin;
53 | public String name;
54 | public String company;
55 | public String blog;
56 | public String location;
57 | public String email;
58 | public Boolean hireable;
59 | public Object bio;
60 | public Integer publicRepos;
61 | public Integer publicGists;
62 | public Integer followers;
63 | public Integer following;
64 | public String createdAt;
65 | public String updatedAt;
66 |
67 |
68 | @Override
69 | public String toString() {
70 | return "User{" +
71 | "login='" + login + '\'' +
72 | ", id=" + id +
73 | ", avatarUrl='" + avatarUrl + '\'' +
74 | ", gravatarId='" + gravatarId + '\'' +
75 | ", url='" + url + '\'' +
76 | ", htmlUrl='" + htmlUrl + '\'' +
77 | ", followersUrl='" + followersUrl + '\'' +
78 | ", followingUrl='" + followingUrl + '\'' +
79 | ", gistsUrl='" + gistsUrl + '\'' +
80 | ", starredUrl='" + starredUrl + '\'' +
81 | ", subscriptionsUrl='" + subscriptionsUrl + '\'' +
82 | ", organizationsUrl='" + organizationsUrl + '\'' +
83 | ", reposUrl='" + reposUrl + '\'' +
84 | ", eventsUrl='" + eventsUrl + '\'' +
85 | ", receivedEventsUrl='" + receivedEventsUrl + '\'' +
86 | ", type='" + type + '\'' +
87 | ", siteAdmin=" + siteAdmin +
88 | ", name='" + name + '\'' +
89 | ", company='" + company + '\'' +
90 | ", blog='" + blog + '\'' +
91 | ", location='" + location + '\'' +
92 | ", email='" + email + '\'' +
93 | ", hireable=" + hireable +
94 | ", bio=" + bio +
95 | ", publicRepos=" + publicRepos +
96 | ", publicGists=" + publicGists +
97 | ", followers=" + followers +
98 | ", following=" + following +
99 | ", createdAt='" + createdAt + '\'' +
100 | ", updatedAt='" + updatedAt + '\'' +
101 | '}';
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/service/RetrofitService.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.service;
27 |
28 |
29 | import retrofit2.Retrofit;
30 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
31 | import retrofit2.converter.gson.GsonConverterFactory;
32 |
33 | /**
34 | * 类描述:RetrofitService
35 | * 创建人:malin.myemail@gmail.com
36 | * 创建时间:16-1-24
37 | * 备注:{@link https://github.com/basil2style/Retrofit-Android-Basic} Thanks for ,Her code is very good ! I made reference to his code,It saves me a lot of time!
38 | * 修改人:
39 | * 修改时间:
40 | * 修改备注:
41 | */
42 | public class RetrofitService {
43 | private static final String API = "https://api.github.com";
44 |
45 | protected RetrofitService() {
46 | retrofit = new Retrofit.Builder()
47 | .baseUrl(API)
48 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
49 | .addConverterFactory(GsonConverterFactory.create())
50 | .build();
51 | }
52 |
53 | private volatile static RetrofitService instance = null;
54 |
55 | private Retrofit retrofit;
56 |
57 | public static RetrofitService getInstance() {
58 | if (instance == null) {
59 | synchronized (RetrofitService.class) {
60 | if (instance == null) {
61 | instance = new RetrofitService();
62 | }
63 | }
64 | }
65 | return instance;
66 | }
67 |
68 | public T createService(Class clz){
69 | return retrofit.create(clz);
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/utils/ClickUtils.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.utils;
27 |
28 | import android.os.SystemClock;
29 | import android.util.Log;
30 |
31 | /**
32 | * 类描述:手机设备的信息
33 | * 创建人:malin.myemail@gmail.com
34 | * 创建时间:16-01-20.下午17:50
35 | * 备注:
36 | */
37 | public class ClickUtils {
38 |
39 | private static final String TAG = ClickUtils.class.getSimpleName();
40 | private static long lastClickTime = 0L;
41 | private static final boolean isDebug = true;
42 | private static final String BLANK_LOG = "\t";
43 |
44 | private ClickUtils() {
45 | }
46 |
47 | /**
48 | * 用于处理频繁点击问题, 如果两次点击小于500毫秒则不予以响应
49 | *
50 | * @return true:是连续的快速点击
51 | */
52 | public static boolean isFastDoubleClick() {
53 | long nowTime = SystemClock.elapsedRealtime();//从开机到现在的毫秒数(手机睡眠(sleep)的时间也包括在内)
54 |
55 | if (isDebug){
56 | Log.d(TAG,"nowTime:" + nowTime);
57 | Log.d(TAG,"lastClickTime:" + lastClickTime);
58 | Log.d(TAG,"时间间隔:"+(nowTime - lastClickTime));
59 | }
60 | if ((nowTime - lastClickTime) < 100000) {
61 |
62 | if (isDebug){
63 | Log.d(TAG,"快速点击");
64 | Log.d(TAG, BLANK_LOG);
65 | }
66 | return true;
67 | } else {
68 | lastClickTime = nowTime;
69 |
70 | if (isDebug){
71 | Log.d(TAG,"lastClickTime:" + lastClickTime);
72 | Log.d(TAG,"不是快速点击");
73 | Log.d(TAG,BLANK_LOG);
74 | }
75 | return false;
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/utils/DeviceInfo.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.utils;
27 |
28 | import android.app.Activity;
29 | import android.util.DisplayMetrics;
30 |
31 | /**
32 | * 类描述:手机设备的信息
33 | * 创建人:malin.myemail@gmail.com
34 | * 创建时间:15-11-10.下午3:26
35 | * 备注:
36 | * 参考项目:Android-Universal-Image-Loader
37 | */
38 | public class DeviceInfo {
39 |
40 | public static int screenWidthForPortrait; // 屏幕宽度
41 | public static int screenHeightForPortrait; // 屏幕高度
42 | public static float mDensity;
43 | public static int mDensityDpi;
44 |
45 |
46 | private volatile static DeviceInfo instance;
47 |
48 | /**
49 | * Returns singleton class instance
50 | */
51 | public static DeviceInfo getInstance() {
52 | if (instance == null) {
53 | synchronized (DeviceInfo.class) {
54 | if (instance == null) {
55 | instance = new DeviceInfo();
56 | }
57 | }
58 | }
59 | return instance;
60 | }
61 |
62 | private DeviceInfo() {
63 |
64 | }
65 |
66 |
67 | /**
68 | * init get device information
69 | *
70 | * @param activity
71 | */
72 | public void initializeScreenInfo(Activity activity) {
73 | DisplayMetrics metric = new DisplayMetrics();
74 | activity.getWindowManager().getDefaultDisplay().getMetrics(metric);
75 | mDensity = metric.density;
76 | mDensityDpi = metric.densityDpi;
77 | if (metric.heightPixels >= metric.widthPixels) {
78 | screenWidthForPortrait = metric.widthPixels;
79 | screenHeightForPortrait = metric.heightPixels;
80 | } else {
81 | screenWidthForPortrait = metric.heightPixels;
82 | screenHeightForPortrait = metric.widthPixels;
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/utils/ImageUtils.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.utils;
27 |
28 | import android.annotation.SuppressLint;
29 | import android.annotation.TargetApi;
30 | import android.content.Context;
31 | import android.content.res.AssetManager;
32 | import android.graphics.Bitmap;
33 | import android.graphics.BitmapFactory;
34 | import android.os.Build;
35 |
36 | import java.io.File;
37 | import java.io.IOException;
38 | import java.io.InputStream;
39 | import java.util.ArrayList;
40 |
41 |
42 | /**
43 | * 类描述:图片处理类
44 | * 创建人:malin.myemail@gmail.com
45 | * 创建时间:15-11-11.
46 | * 参考项目:
47 | */
48 | public class ImageUtils {
49 |
50 | private static final String TAG = "PaoWuXian_RxJava";
51 |
52 | private ImageUtils() {
53 | }
54 |
55 | /**
56 | * 从assets文件夹中获取制定路径的图片的Bitmap
57 | *
58 | * @param context:上下文
59 | * @param imagePathName:图片路径的名称:例如: paowuxian/04.jpg
60 | * @param reqWidth:图片需要显示的宽
61 | * @param reqHeight:图片需要显示的高
62 | * @return
63 | */
64 | public static Bitmap getImageBitmapFromAssetsFolderThroughImagePathName(Context context, String imagePathName, int reqWidth, int reqHeight) {
65 | BitmapFactory.Options opts = new BitmapFactory.Options();
66 | opts.inJustDecodeBounds = true;
67 | Bitmap bitmap = null;
68 | AssetManager assetManager = context.getResources().getAssets();
69 | InputStream inputStream;
70 |
71 | try {
72 | inputStream = assetManager.open(imagePathName);
73 | inputStream.mark(Integer.MAX_VALUE);
74 | } catch (IOException e) {
75 | e.printStackTrace();
76 | return null;
77 | }catch (OutOfMemoryError e) {
78 | e.printStackTrace();
79 | System.gc();
80 | return null;
81 | }
82 |
83 | try {
84 | if (inputStream != null) {
85 | BitmapFactory.decodeStream(inputStream, null, opts);
86 | inputStream.reset();
87 | } else {
88 | return null;
89 | }
90 | } catch (OutOfMemoryError e) {
91 | e.printStackTrace();
92 | System.gc();
93 | return null;
94 | } catch (Exception e) {
95 | e.printStackTrace();
96 | return null;
97 | }
98 | opts.inSampleSize = calculateInSampleSiez(opts, reqWidth, reqHeight);
99 | // Log.d(TAG,""+opts.inSampleSize);
100 | opts.inJustDecodeBounds = false;
101 | opts.inPreferredConfig = Bitmap.Config.RGB_565;
102 | opts.inPurgeable = true;
103 | opts.inInputShareable = true;
104 | opts.inDither = false;
105 | opts.inTempStorage = new byte[512 * 1024];
106 | try {
107 | if (inputStream != null) {
108 | bitmap = BitmapFactory.decodeStream(inputStream, null, opts);
109 | } else {
110 | return null;
111 | }
112 | } catch (OutOfMemoryError e) {
113 | e.printStackTrace();
114 | System.gc();
115 | return null;
116 | } catch (Exception e) {
117 | e.printStackTrace();
118 | return null;
119 | } finally {
120 | if (inputStream != null) {
121 | try {
122 | inputStream.close();
123 | } catch (Exception e) {
124 | e.printStackTrace();
125 | return null;
126 | }
127 | }
128 | }
129 | // Log.d(TAG,"w:"+bitmap.getWidth()+" h:"+bitmap.getHeight());
130 | if (bitmap != null) {
131 | try {
132 | bitmap = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, true);
133 | }catch (OutOfMemoryError outOfMemoryError){
134 | outOfMemoryError.printStackTrace();
135 | System.gc();
136 | return null;
137 | }
138 |
139 | }
140 | return bitmap;
141 | }
142 |
143 |
144 | /**
145 | * 获取一个合适的缩放系数(2^n)
146 | *
147 | * @param options:Options
148 | * @param reqWidth:图片需要显示的宽
149 | * @param reqHeight:图片需要显示的高
150 | * @return 缩放系数, 2的次方
151 | * @Link http://hukai.me/android-training-course-in-chinese/graphics/displaying-bitmaps/load-bitmap.html
152 | */
153 | public static int calculateInSampleSiez(BitmapFactory.Options options, int reqWidth, int reqHeight) {
154 | // Raw height and width of image
155 | final int height = options.outHeight;
156 | final int width = options.outWidth;
157 | int inSampleSize = 1;
158 |
159 | if (height > reqHeight || width > reqWidth) {
160 |
161 | final int halfHeight = height / 2;
162 | final int halfWidth = width / 2;
163 |
164 | // Calculate the largest inSampleSize value that is a power of 2 and keeps both
165 | // height and width larger than the requested height and width.
166 | while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
167 | inSampleSize *= 2;
168 | }
169 | }
170 | return inSampleSize;
171 | }
172 |
173 |
174 | /**
175 | * 获取assets文件夹下某个文件夹中所有图片路径的集合
176 | *
177 | * 例如:assets/paowuxian 这个目录下的图片路径的集合
178 | * {
179 | * paowuxian/04.jpg,
180 | * paowuxian/05.jpg,
181 | * paowuxian/06.jpg,
182 | * paowuxian/07.jpg,
183 | *
184 | * }
185 | *
186 | * @param context:上下文
187 | * @param folderName:文件夹名称
188 | * @return
189 | */
190 | public static ArrayList getAssetsImageNamePathList(Context context, String folderName) {
191 |
192 | ArrayList imagePathList = new ArrayList<>();
193 |
194 | String[] imageNameArray = getAssetsImageNameArray(context, folderName);
195 |
196 | if (imageNameArray != null && imageNameArray.length > 0 && folderName != null && !folderName.replaceAll(" ", "").trim().equals("")) {
197 | for (String imageName : imageNameArray) {
198 | imagePathList.add(new StringBuffer(folderName).append(File.separator).append(imageName).toString());
199 | }
200 | }
201 |
202 | return imagePathList;
203 | }
204 |
205 |
206 | /**
207 | * 得到assets文件夹下--某个文件夹下--所有文件的文件名
208 | * 例如:assets/paowuxian 这个目录下的图片名称(包含后缀)集合
209 | * {
210 | * 04.jpg,
211 | * 05.jpg,
212 | * 06.jpg,
213 | * 07.jpg,
214 | * }
215 | *
216 | * @param context:上下文
217 | * @param folderName:文件夹名称
218 | * @return
219 | */
220 | private static String[] getAssetsImageNameArray(Context context, String folderName) {
221 | String[] imageNameArray = null;
222 | try {
223 | imageNameArray = context.getAssets().list(folderName);
224 | } catch (IOException e) {
225 | e.printStackTrace();
226 | }
227 | return imageNameArray;
228 | }
229 |
230 |
231 | /**
232 | * 将本地ResFolder图片转换为Bitmap
233 | */
234 |
235 | /**
236 | * inDensity 就是原始资源的 density
237 | *
238 | * inTargetDensity 就是屏幕的 density。
239 | */
240 |
241 | public static Bitmap getLocalBitmapFromResFolder(Context context, int resId) {
242 | return BitmapFactory.decodeResource(context.getResources(), resId);
243 | }
244 |
245 | /**
246 | * 获取Bitmap大小
247 | * @param bitmap
248 | * @return
249 | */
250 | @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
251 | public static int getBitmapSize2(Bitmap bitmap) {
252 | if (bitmap==null) return 0;
253 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
254 | return bitmap.getRowBytes() * bitmap.getHeight();
255 | } else {
256 | return bitmap.getByteCount();
257 | }
258 | }
259 |
260 | /**
261 | * 获取Bitmap大小
262 | * @param bitmap
263 | * @return
264 | */
265 | @SuppressLint("NewApi")
266 | public static int getBitmapSize(Bitmap bitmap) {
267 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // API 19
268 | return bitmap.getAllocationByteCount();
269 | }
270 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {// API 12
271 | return bitmap.getByteCount();
272 | }
273 | return bitmap.getRowBytes() * bitmap.getHeight(); // earlier version
274 | }
275 | }
276 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/utils/RecycleBitmap.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.utils;
27 |
28 |
29 | import android.graphics.Bitmap;
30 | import android.graphics.drawable.BitmapDrawable;
31 | import android.graphics.drawable.Drawable;
32 | import android.widget.ImageView;
33 |
34 | /**
35 | * 类描述:回收ImageView占用的图像内存
36 | * 创建人:malin.myemail@gmail.com
37 | * 创建时间:15-11-21.
38 | * 参考内容:http://blog.csdn.net/intbird/article/details/19905549
39 | */
40 |
41 | public class RecycleBitmap {
42 | private RecycleBitmap() {
43 | }
44 |
45 | /**
46 | * 回收ImageView占用的图像内存;
47 | *
48 | * @param imageView
49 | */
50 | public static void recycleImageView(ImageView imageView) {
51 | if (imageView == null) {
52 | return;
53 | }
54 |
55 | Drawable drawable = imageView.getDrawable();
56 | if (drawable != null && drawable instanceof BitmapDrawable) {
57 | BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
58 | Bitmap bitmap = bitmapDrawable.getBitmap();
59 | if (bitmap != null && !bitmap.isRecycled()) {
60 | bitmap.recycle();
61 | bitmap = null;
62 | imageView.setImageBitmap(null);
63 | }
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/utils/RxUtils.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.utils;
27 |
28 | import rx.Subscription;
29 | import rx.subscriptions.CompositeSubscription;
30 |
31 | public class RxUtils {
32 |
33 | private RxUtils() {
34 | }
35 |
36 | public static void unsubscribeIfNotNull(Subscription subscription) {
37 | if (subscription != null) {
38 | subscription.unsubscribe();
39 | }
40 | }
41 |
42 | public static CompositeSubscription getNewCompositeSubIfUnsubscribed(CompositeSubscription subscription) {
43 | if (subscription == null || subscription.isUnsubscribed()) {
44 | return new CompositeSubscription();
45 | }
46 |
47 | return subscription;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/malin/rxjava/utils/ToastUtil.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2015 malin
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 |
26 | package com.malin.rxjava.utils;
27 |
28 | import android.content.Context;
29 | import android.widget.Toast;
30 |
31 | /**
32 | * 类描述:防止Toast显示多次
33 | * 创建人:malin.myemail@gmail.com
34 | * 创建时间:16-01-20.下午17:50
35 | * 备注:
36 | */
37 | public class ToastUtil {
38 |
39 |
40 | private static String mOldMessage = "";
41 | protected static Toast mToast = null;
42 | private static long mFirstTime = 0L;
43 | private static long mSecondTime = 0L;
44 |
45 |
46 | private volatile static ToastUtil instance;
47 |
48 | /**
49 | * Returns singleton class instance
50 | */
51 | public static ToastUtil getInstance() {
52 | if (instance == null) {
53 | synchronized (ToastUtil.class) {
54 | if (instance == null) {
55 | instance = new ToastUtil();
56 | }
57 | }
58 | }
59 | return instance;
60 | }
61 |
62 | private ToastUtil() {
63 |
64 | }
65 |
66 |
67 | public void showToast(Context context, String message) {
68 | if (mToast == null) {
69 | synchronized (ToastUtil.class) {
70 | if (mToast == null) {
71 | mToast = Toast.makeText(context, message, Toast.LENGTH_SHORT);
72 | mToast.show();
73 | mFirstTime = System.currentTimeMillis();
74 | }
75 | }
76 |
77 | } else {
78 | mSecondTime = System.currentTimeMillis();
79 | if (message.equals(mOldMessage)) {
80 | if (mSecondTime - mFirstTime > Toast.LENGTH_SHORT) {
81 | mToast.show();
82 | }
83 | } else {
84 | mOldMessage = message;
85 | mToast.setText(message);
86 | mToast.show();
87 | }
88 | }
89 | mFirstTime = mSecondTime;
90 | }
91 |
92 |
93 | public void showToast(Context context, int resId) {
94 | showToast(context, context.getString(resId));
95 | }
96 |
97 |
98 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
43 |
44 |
45 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_log.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/malin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidmalin/RxjavaSample/3a13759b2db1105024b94be75ad81906a00b59c8/app/src/main/res/mipmap-xhdpi/malin.jpg
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | RxJavaSample
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | RxJavaSample
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | jcenter()
5 | mavenCentral()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.3'
9 | // NOTE: Do not place your application dependencies here; they belong
10 | // in the individual module build.gradle files
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | jcenter()
17 | }
18 | }
19 |
20 | task clean(type: Delete) {
21 | delete rootProject.buildDir
22 | }
23 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Wed Jan 27 10:24:18 CST 2016
16 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidmalin/RxjavaSample/3a13759b2db1105024b94be75ad81906a00b59c8/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Dec 16 15:33:33 CST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/qrcode/dowload_qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidmalin/RxjavaSample/3a13759b2db1105024b94be75ad81906a00b59c8/qrcode/dowload_qrcode.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------