├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── demo │ │ └── maat │ │ └── hello_rxjava │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── demo │ │ │ └── maat │ │ │ └── hello_rxjava │ │ │ ├── DebounceEditTextActivity.java │ │ │ ├── DebounceEditTextFragment.java │ │ │ ├── MainActivity.java │ │ │ ├── Operators1Activity.java │ │ │ ├── Operators1Fragment.java │ │ │ ├── Operators2Activity.java │ │ │ ├── Operators2Fragment.java │ │ │ ├── PollingActivity.java │ │ │ ├── PollingFragment.java │ │ │ ├── RxAndroidActivity.java │ │ │ ├── RxAndroidFragment.java │ │ │ ├── RxJavaMainActivity.java │ │ │ ├── RxJavaRetrofitActivity.java │ │ │ ├── RxJavaRetrofitFragment.java │ │ │ ├── SchedulerActivity.java │ │ │ ├── SchedulerFragment.java │ │ │ ├── common │ │ │ ├── activities │ │ │ │ └── SampleActivityBase.java │ │ │ └── logger │ │ │ │ ├── Log.java │ │ │ │ ├── LogFragment.java │ │ │ │ ├── LogNode.java │ │ │ │ ├── LogView.java │ │ │ │ ├── LogWrapper.java │ │ │ │ └── MessageOnlyLogFilter.java │ │ │ └── retrofit │ │ │ ├── ZhihuApi.java │ │ │ └── zhihu │ │ │ ├── ZhihuDaily.java │ │ │ ├── ZhihuDailyItem.java │ │ │ └── ZhihuManager.java │ └── res │ │ ├── drawable │ │ └── tile.9.png │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── debounce_activity_main.xml │ │ ├── debounce_fragment.xml │ │ ├── operator1_activity_main.xml │ │ ├── operator2_activity_main.xml │ │ ├── operators1_fragment.xml │ │ ├── operators2_fragment.xml │ │ ├── polling_activity_main.xml │ │ ├── polling_fragment.xml │ │ ├── retrofit_fragment.xml │ │ ├── rxandroid_fragment.xml │ │ ├── rxjava_activity_main.xml │ │ ├── scheduler_activity_main.xml │ │ └── scheduler_fragment.xml │ │ ├── menu │ │ └── main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ ├── dimens.xml │ │ ├── fragmentview_strings.xml │ │ ├── template-dimens.xml │ │ └── template-styles.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── demo │ └── maat │ └── hello_rxjava │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots ├── LongOperation.gif ├── debounce.gif ├── just.gif ├── just.png ├── just1.gif ├── just1.png ├── just1p.png ├── just2.gif ├── just2.png ├── just2p.png ├── just3.gif ├── just3.png ├── just3p.png ├── just4.gif ├── just4.png ├── just4p.png ├── just5.gif ├── just5.png ├── just5p.png ├── just6.gif ├── just6.png ├── just6p.png ├── justp.png ├── polling.gif ├── rxandroid.gif └── rxjavaretrofit.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | /.idea/ 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Learning RxJava(RxJava详解) 2 | **为什么做这个项目:** 学习Rxjava,基本所有人都会看扔物线的《给Android开发者Rxjava的详解》,可以说是国内最理想的Rxjava教程了。这片文章后半部分讲对线程的操作,相信很多人都不太懂。这个项目通过最简单的方式,对Rxjava线程操作的进行讲解,让大家彻底明白Rxjava的核心内容。所以,在学习这个项目前先看扔物线大哥的文章。 3 | 4 | RxJava的精妙之处就是异步操作极其方便,也就是Schedulers的使用,本项目可以让大家彻底掌握Schedulers的使用,还有常用的操作符、RxAndroid...的使用详解。就是用最简单移动的方式把Rxjava讲明白. 5 | 6 | 7 | ## 详解 (Details Explain) 8 | 我们可以把Schedulers看作线程控制符,一共五种线程控制符,可以通过这些线程控制符切换不同的线程。以下是五种线程控制符的区别: 9 | 10 | 1. `Schedulers.immediate()` 在当前线程运行,相当于不切换线程。这是默认的 Scheduler。 11 | 12 | 13 | 14 | 2. `Schedulers.newThread()`总是启用新线程,并在新线程执行操作。 15 | 16 | 17 | 18 | 3. `Schedulers.io()` I/O 操作(读写文件、数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。 19 | 20 | 21 | 4. `Schedulers.computation()` 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。 22 | 23 | 24 | 5. `AndroidSchedulers.mainThread()` 切换到主线程,指定的操作将在Android 主线程运行。 25 | 26 | 27 | 28 | ` 其实我们常用的就2种:Schedulers.io()和AndroidSchedulers.mainThread()` 29 | 30 | > 以下几个例子都是使用Observable.just(1,2,3)创建被观察对象,观察者输出1,2,3. 31 | 32 | > This example show how to use make a few threads that we can watch their actions 33 | 34 | 35 | #### 1. 基本使用 36 | 37 | 38 | 39 | 40 | #### 2. 使用 subscribeOn(Schedulers.io())设置被观察者的线程 41 | 42 | 43 | > 以下几个例子中看不出被观察者发生在什么线程,使用Observeble.create()创建被观察者可以看出发生在什么线程,可参看源码中的其它Demo。 44 | 45 | #### 3. 使用 subscribeOn(Schedulers.io()) 和 observeOn() 设置被观察者和观察者的线程 46 | 47 | 48 | 49 | 50 | #### 4. 使用Schedulers.io()指定被观察者产生事件的线程,然后使用Map对数据转换,这里只是在每个数据后面加‘a’。 51 | 52 | 53 | 54 | 55 | 56 | #### 5. 使用Schedulers.io()指定被观察者产生事件的线程,使用Map对数据转换,在每个数据后面加‘a’,使用AndroidSchedulers.mainThread()切换到主线程,然后使用Map变换,每个数据后加‘b’,输出结果。 57 | 58 | 59 | 60 | 61 | #### 6. 使用Schedulers.io()指定被观察者产生事件的线程,使用Map对数据转换,在每个数据后面加‘a’,使用AndroidSchedulers.mainThread()切换到主线程,然后使用Map变换,每个数据后加‘b’,再用Schedulers.io()切换线程,用Map对数据加‘c’,输出结果。 62 | 63 | 64 | 65 | 66 | #### 7.这个例子不同的是使用了两次subscribeOn()来指定被观察者的线程,最终最上面的subscribeOn()起作用,下面的subscribeOn()不起作用。然后使用Map对数据转换,这里只是在每个数据后面加‘a’,使用Schedulers.io()切换线程,然后使用Map变换,每个数据后加‘b’,再用AndroidSchedulers.mainThread()切换主线程,用Map对数据加‘c’,最后再切换到非主线程,输出结果。 67 | 68 | 69 | 70 | 71 | >最终发现设置被观察者的线程只有最上面的起作用,下面的不起作用。 72 | 73 | 74 | `更多的例子请看源码` 75 | 76 | ## About me 77 | 78 | An android developer in Beijing.Welcome to offer me an [Interview invitation](mailto:maat.xing@gmail.com). If you have any new idea about this project, feel free to [contact me](mailto:maat.xing@gmail.com). :smiley: 79 | 80 | 81 | 82 | 83 | 84 | 85 | License 86 | ======= 87 | 88 | Copyright 2016 Maat 89 | 90 | 91 | Licensed under the Apache License, Version 2.0 (the "License"); 92 | you may not use this file except in compliance with the License. 93 | You may obtain a copy of the License at 94 | 95 | http://www.apache.org/licenses/LICENSE-2.0 96 | 97 | Unless required by applicable law or agreed to in writing, software 98 | distributed under the License is distributed on an "AS IS" BASIS, 99 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 100 | See the License for the specific language governing permissions and 101 | limitations under the License. 102 | 103 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'android-apt' 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion '25.0.0' 6 | defaultConfig { 7 | applicationId "com.demo.maat.hello_rxjava" 8 | minSdkVersion 16 9 | targetSdkVersion 24 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile 'com.android.support:appcompat-v7:24.2.1' 28 | testCompile 'junit:junit:4.12' 29 | compile 'com.jakewharton:butterknife:8.4.0' 30 | apt 'com.jakewharton:butterknife-compiler:8.4.0' 31 | compile 'io.reactivex:rxandroid:1.0.1' 32 | // Because RxAndroid releases are few and far between, it is recommended you also 33 | // explicitly depend on RxJava's latest version for bug fixes and new features. 34 | compile 'io.reactivex:rxjava:1.0.14' 35 | compile 'io.reactivex:rxjava-math:1.0.0' 36 | compile 'com.jakewharton.rxbinding:rxbinding:0.2.0' 37 | /*rotrofit*/ 38 | compile 'com.squareup.retrofit2:retrofit:+' 39 | compile 'com.squareup.retrofit2:converter-gson:+' 40 | compile 'com.squareup.retrofit2:adapter-rxjava:+' 41 | compile 'com.google.code.gson:gson:+' 42 | compile 'io.reactivex:rxandroid:1.2.1' 43 | } 44 | -------------------------------------------------------------------------------- /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 /Users/xinghongfei/Downloads/android-sdk--mac-r24-updated/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/androidTest/java/com/demo/maat/hello_rxjava/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.demo.maat.hello_rxjava", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 23 | 27 | 31 | 35 | 39 | 43 | 47 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/DebounceEditTextActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package com.demo.maat.hello_rxjava; 19 | 20 | import android.os.Bundle; 21 | import android.support.v4.app.FragmentTransaction; 22 | 23 | import com.demo.maat.hello_rxjava.common.activities.SampleActivityBase; 24 | import com.demo.maat.hello_rxjava.common.logger.Log; 25 | import com.demo.maat.hello_rxjava.common.logger.LogFragment; 26 | import com.demo.maat.hello_rxjava.common.logger.LogWrapper; 27 | import com.demo.maat.hello_rxjava.common.logger.MessageOnlyLogFilter; 28 | 29 | 30 | public class DebounceEditTextActivity extends SampleActivityBase { 31 | 32 | public static final String TAG = "DebounceEditTextActivity"; 33 | 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.debounce_activity_main); 39 | 40 | if (savedInstanceState == null) { 41 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 42 | DebounceEditTextFragment fragment = new DebounceEditTextFragment(); 43 | transaction.replace(R.id.sample_content_fragment, fragment); 44 | transaction.commit(); 45 | } 46 | } 47 | 48 | 49 | 50 | 51 | @Override 52 | public void initializeLogging() { 53 | LogWrapper logWrapper = new LogWrapper(); 54 | Log.setLogNode(logWrapper); 55 | 56 | MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter(); 57 | logWrapper.setNext(msgFilter); 58 | 59 | // On screen logging via a fragment with a TextView. 60 | LogFragment logFragment = (LogFragment) getSupportFragmentManager() 61 | .findFragmentById(R.id.log_fragment); 62 | msgFilter.setNext(logFragment.getLogView()); 63 | 64 | Log.i(TAG, "Ready"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/DebounceEditTextFragment.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.EditText; 10 | 11 | import com.demo.maat.hello_rxjava.common.logger.Log; 12 | import com.jakewharton.rxbinding.widget.RxTextView; 13 | import com.jakewharton.rxbinding.widget.TextViewTextChangeEvent; 14 | 15 | import java.util.concurrent.TimeUnit; 16 | 17 | import butterknife.BindView; 18 | import butterknife.ButterKnife; 19 | import rx.Observer; 20 | import rx.Subscription; 21 | import rx.android.schedulers.AndroidSchedulers; 22 | import rx.subscriptions.CompositeSubscription; 23 | 24 | 25 | public class DebounceEditTextFragment extends Fragment { 26 | 27 | 28 | static final String TAG = "DebounceEditTextFragment"; 29 | 30 | @BindView(R.id.edit_search) 31 | EditText mEditSearch; 32 | int N=0; 33 | private Subscription subscribe; 34 | private CompositeSubscription mCompositeSubscription; 35 | ; 36 | 37 | @Override 38 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 39 | Bundle savedInstanceState) { 40 | View view = inflater.inflate(R.layout.debounce_fragment, container, false); 41 | ButterKnife.bind(this, view); 42 | mCompositeSubscription = new CompositeSubscription(); 43 | return view; 44 | } 45 | 46 | @Override 47 | public void onResume() { 48 | super.onResume(); 49 | } 50 | 51 | @Override 52 | public void onViewCreated(View view, Bundle savedInstanceState) { 53 | super.onViewCreated(view, savedInstanceState); 54 | 55 | } 56 | 57 | 58 | 59 | @Override 60 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 61 | super.onActivityCreated(savedInstanceState); 62 | subscribe= RxTextView.textChangeEvents(mEditSearch)// 63 | .debounce(400, TimeUnit.MILLISECONDS)// default Scheduler is Computation 64 | .observeOn(AndroidSchedulers.mainThread())// 65 | .subscribe(new Observer() { 66 | @Override 67 | public void onCompleted() { 68 | printLog("Completed"); 69 | } 70 | 71 | @Override 72 | public void onError(Throwable e) { 73 | printLog("Error"); 74 | } 75 | 76 | @Override 77 | public void onNext(TextViewTextChangeEvent onTextChangeEvent) { 78 | printLog(onTextChangeEvent.text().toString()); 79 | } 80 | } 81 | ); 82 | mCompositeSubscription.add(subscribe); 83 | } 84 | 85 | private void printLog(String s) { 86 | Log.i(TAG, s); 87 | } 88 | 89 | @Override 90 | public void onDestroy() { 91 | super.onDestroy(); 92 | mCompositeSubscription.unsubscribe(); 93 | } 94 | 95 | 96 | } 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.View; 8 | import android.widget.Button; 9 | 10 | import butterknife.BindView; 11 | import butterknife.ButterKnife; 12 | import butterknife.OnClick; 13 | 14 | public class MainActivity extends AppCompatActivity { 15 | 16 | 17 | @Nullable @BindView(R.id.btn_rxjava) 18 | Button mBtnRxjava; 19 | @BindView(R.id.btn_retrofit) 20 | Button mBtnRetrofit; 21 | @BindView(R.id.btn_rxandroid) 22 | Button mBtnRxAndroid; 23 | 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_main); 29 | ButterKnife.bind(this); 30 | 31 | } 32 | 33 | 34 | @OnClick({R.id.btn_rxjava, R.id.btn_retrofit,R.id.btn_rxandroid}) 35 | public void onClick(View view) { 36 | switch (view.getId()) { 37 | case R.id.btn_rxjava: 38 | Intent intent=new Intent(MainActivity.this,RxJavaMainActivity.class); 39 | startActivity(intent); 40 | break; 41 | case R.id.btn_retrofit: 42 | Intent retrofit=new Intent(MainActivity.this,RxJavaRetrofitActivity.class); 43 | startActivity(retrofit); 44 | break; 45 | case R.id.btn_rxandroid: 46 | Intent rxandroid=new Intent(MainActivity.this,RxAndroidActivity.class); 47 | startActivity(rxandroid); 48 | break; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/Operators1Activity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package com.demo.maat.hello_rxjava; 19 | 20 | import android.os.Bundle; 21 | import android.support.v4.app.FragmentTransaction; 22 | 23 | import com.demo.maat.hello_rxjava.common.activities.SampleActivityBase; 24 | import com.demo.maat.hello_rxjava.common.logger.Log; 25 | import com.demo.maat.hello_rxjava.common.logger.LogFragment; 26 | import com.demo.maat.hello_rxjava.common.logger.LogWrapper; 27 | import com.demo.maat.hello_rxjava.common.logger.MessageOnlyLogFilter; 28 | 29 | 30 | public class Operators1Activity extends SampleActivityBase { 31 | 32 | public static final String TAG = "Operators1Activity"; 33 | 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.operator1_activity_main); 39 | 40 | if (savedInstanceState == null) { 41 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 42 | Operators1Fragment fragment = new Operators1Fragment(); 43 | transaction.replace(R.id.sample_content_fragment, fragment); 44 | transaction.commit(); 45 | } 46 | } 47 | 48 | 49 | 50 | 51 | @Override 52 | public void initializeLogging() { 53 | LogWrapper logWrapper = new LogWrapper(); 54 | Log.setLogNode(logWrapper); 55 | 56 | MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter(); 57 | logWrapper.setNext(msgFilter); 58 | 59 | // On screen logging via a fragment with a TextView. 60 | LogFragment logFragment = (LogFragment) getSupportFragmentManager() 61 | .findFragmentById(R.id.log_fragment); 62 | msgFilter.setNext(logFragment.getLogView()); 63 | 64 | Log.i(TAG, "Ready"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/Operators1Fragment.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.Button; 9 | 10 | import com.demo.maat.hello_rxjava.common.logger.Log; 11 | 12 | import java.util.concurrent.TimeUnit; 13 | 14 | import butterknife.BindView; 15 | import butterknife.ButterKnife; 16 | import butterknife.OnClick; 17 | import rx.Observable; 18 | import rx.Subscriber; 19 | import rx.Subscription; 20 | import rx.functions.Action0; 21 | import rx.functions.Action1; 22 | import rx.functions.Func1; 23 | import rx.functions.Func2; 24 | import rx.subscriptions.CompositeSubscription; 25 | 26 | import static rx.Observable.timer; 27 | 28 | 29 | public class Operators1Fragment extends Fragment { 30 | 31 | 32 | static final String TAG = "Operators1Fragment"; 33 | @BindView(R.id.btn_just) 34 | Button mBtnJust; 35 | @BindView(R.id.btn_from) 36 | Button mBtnFrom; 37 | @BindView(R.id.btn_repeat) 38 | Button mBtnRepeat; 39 | @BindView(R.id.btn_repeatwhen) 40 | Button mBtnRepeatwhen; 41 | @BindView(R.id.btn_interval) 42 | Button mBtnInterval; 43 | @BindView(R.id.btn_timer) 44 | Button mBtnTimer; 45 | @BindView(R.id.btn_range) 46 | Button mBtnRange; 47 | 48 | 49 | private CompositeSubscription mCompositeSubscription; 50 | ; 51 | 52 | @Override 53 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 54 | Bundle savedInstanceState) { 55 | View view = inflater.inflate(R.layout.operators1_fragment, container, false); 56 | ButterKnife.bind(this, view); 57 | mCompositeSubscription = new CompositeSubscription(); 58 | return view; 59 | } 60 | 61 | @Override 62 | public void onResume() { 63 | super.onResume(); 64 | } 65 | 66 | @Override 67 | public void onViewCreated(View view, Bundle savedInstanceState) { 68 | super.onViewCreated(view, savedInstanceState); 69 | 70 | } 71 | 72 | 73 | @OnClick({R.id.btn_just, R.id.btn_from, R.id.btn_repeat, R.id.btn_repeatwhen, R.id.btn_interval, R.id.btn_timer, R.id.btn_range}) 74 | public void onClick(View view) { 75 | switch (view.getId()) { 76 | case R.id.btn_just: 77 | doJustOperation(); 78 | break; 79 | case R.id.btn_from: 80 | doFromOperation(); 81 | break; 82 | case R.id.btn_repeat: 83 | doRepeatOperation(); 84 | break; 85 | case R.id.btn_repeatwhen: 86 | doRepeatWhenOperation(); 87 | break; 88 | case R.id.btn_interval: 89 | doIntervalOperation(); 90 | break; 91 | case R.id.btn_timer: 92 | doTimerOperation(); 93 | break; 94 | case R.id.btn_range: 95 | doRangeOperation(); 96 | break; 97 | } 98 | } 99 | 100 | /** 101 | * 从3开始连续产生10个数字 102 | */ 103 | 104 | private void doRangeOperation() { 105 | Subscription rangeSub =Observable.range(3,10).subscribe(new Subscriber() { 106 | @Override 107 | public void onCompleted() { 108 | printLog("Completed"); 109 | } 110 | 111 | @Override 112 | public void onError(Throwable e) { 113 | printLog("Error"); 114 | } 115 | 116 | @Override 117 | public void onNext(Integer i) { 118 | printLog("Next"+i); 119 | } 120 | }); 121 | mCompositeSubscription.add(rangeSub); 122 | 123 | } 124 | 125 | /** 126 | * 每隔1秒输出一个数字 127 | */ 128 | private void doTimerOperation() { 129 | 130 | Subscription timerSub=Observable.timer(1, 1, TimeUnit.SECONDS).subscribe(new Subscriber() { 131 | @Override 132 | public void onCompleted() { 133 | printLog("Completed"); 134 | } 135 | 136 | @Override 137 | public void onError(Throwable e) { 138 | printLog("Error"); 139 | } 140 | 141 | @Override 142 | public void onNext(Long aLong) { 143 | printLog("Next" + aLong); 144 | } 145 | }); 146 | mCompositeSubscription.add(timerSub); 147 | } 148 | 149 | private void doIntervalOperation() { 150 | Subscription intervalSub=Observable.interval(1, TimeUnit.SECONDS).subscribe(new Subscriber() { 151 | @Override 152 | public void onCompleted() { 153 | printLog("Completed"); 154 | 155 | } 156 | 157 | @Override 158 | public void onError(Throwable e) { 159 | printLog("Error"); 160 | 161 | } 162 | 163 | @Override 164 | public void onNext(Long aLong) { 165 | printLog("Next" + aLong); 166 | } 167 | }); 168 | mCompositeSubscription.add(intervalSub); 169 | } 170 | 171 | /** 172 | * 完成一次之后,再每隔1秒重复1次,共重复3次。 173 | */ 174 | 175 | private void doRepeatWhenOperation() { 176 | Observable.just(1, 2, 3).repeatWhen(new Func1, Observable>() { 177 | @Override 178 | public Observable call(Observable observable) { 179 | //重复3次 180 | return observable.zipWith(Observable.range(1, 3), new Func2() { 181 | @Override 182 | public Integer call(Void aVoid, Integer integer) { 183 | return integer; 184 | } 185 | }).flatMap(new Func1>() { 186 | @Override 187 | public Observable call(Integer integer) { 188 | printLog("delay repeat" + integer); 189 | //1秒钟重复一次 190 | return timer(1, TimeUnit.SECONDS); 191 | } 192 | }); 193 | } 194 | }).subscribe(new Subscriber() { 195 | @Override 196 | public void onCompleted() { 197 | printLog("Completed"); 198 | } 199 | 200 | @Override 201 | public void onError(Throwable e) { 202 | printLog("Error"); 203 | } 204 | 205 | @Override 206 | public void onNext(Integer value) { 207 | printLog("Next" + value); 208 | } 209 | }); 210 | } 211 | // 从1开始输出3个数,重复2次 212 | private void doRepeatOperation() { 213 | Observable.range(1, 3).repeat(2).subscribe(new Subscriber() { 214 | @Override 215 | public void onCompleted() { 216 | printLog("Completed"); 217 | } 218 | 219 | @Override 220 | public void onError(Throwable e) { 221 | printLog("Error"); 222 | } 223 | 224 | @Override 225 | public void onNext(Integer i) { 226 | printLog("Nest" + i); 227 | } 228 | }); 229 | } 230 | 231 | /** 232 | * 接受一个数组,与just的区别就是接受的参数不同 233 | */ 234 | private void doFromOperation() { 235 | Integer[] items = {0, 1, 2, 3, 4, 5}; 236 | Observable from = Observable.from(items); 237 | 238 | from.subscribe( 239 | new Action1() { 240 | @Override 241 | public void call(Integer item) { 242 | printLog("Next" + item); 243 | } 244 | }, 245 | new Action1() { 246 | @Override 247 | public void call(Throwable error) { 248 | printLog("Error"); 249 | } 250 | }, 251 | new Action0() { 252 | @Override 253 | public void call() { 254 | printLog("Compeleted"); 255 | } 256 | } 257 | ); 258 | 259 | } 260 | 261 | private void doJustOperation() { 262 | Subscription subscription = Observable.just(1, 2, 3, 4, 5) 263 | .subscribe(new Subscriber() { 264 | @Override 265 | public void onNext(Integer item) { 266 | printLog("Next" + item); 267 | } 268 | 269 | @Override 270 | public void onError(Throwable error) { 271 | printLog("Error"); 272 | } 273 | 274 | @Override 275 | public void onCompleted() { 276 | printLog("Completed"); 277 | } 278 | }); 279 | mCompositeSubscription.add(subscription); 280 | } 281 | 282 | private void printLog(String s) { 283 | Log.i(TAG, s); 284 | } 285 | 286 | @Override 287 | public void onDestroy() { 288 | super.onDestroy(); 289 | mCompositeSubscription.unsubscribe(); 290 | } 291 | } 292 | 293 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/Operators2Activity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package com.demo.maat.hello_rxjava; 19 | 20 | import android.os.Bundle; 21 | import android.support.v4.app.FragmentTransaction; 22 | 23 | import com.demo.maat.hello_rxjava.common.activities.SampleActivityBase; 24 | import com.demo.maat.hello_rxjava.common.logger.Log; 25 | import com.demo.maat.hello_rxjava.common.logger.LogFragment; 26 | import com.demo.maat.hello_rxjava.common.logger.LogWrapper; 27 | import com.demo.maat.hello_rxjava.common.logger.MessageOnlyLogFilter; 28 | 29 | 30 | public class Operators2Activity extends SampleActivityBase { 31 | 32 | public static final String TAG = "Operators1Activity"; 33 | 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.operator2_activity_main); 39 | 40 | if (savedInstanceState == null) { 41 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 42 | Operators2Fragment fragment = new Operators2Fragment(); 43 | transaction.replace(R.id.sample_content_fragment, fragment); 44 | transaction.commit(); 45 | } 46 | } 47 | 48 | 49 | 50 | 51 | @Override 52 | public void initializeLogging() { 53 | LogWrapper logWrapper = new LogWrapper(); 54 | Log.setLogNode(logWrapper); 55 | 56 | MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter(); 57 | logWrapper.setNext(msgFilter); 58 | 59 | // On screen logging via a fragment with a TextView. 60 | LogFragment logFragment = (LogFragment) getSupportFragmentManager() 61 | .findFragmentById(R.id.log_fragment); 62 | msgFilter.setNext(logFragment.getLogView()); 63 | 64 | Log.i(TAG, "Ready"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/Operators2Fragment.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.Button; 9 | 10 | import com.demo.maat.hello_rxjava.common.logger.Log; 11 | 12 | import java.util.List; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | import butterknife.BindView; 16 | import butterknife.ButterKnife; 17 | import butterknife.OnClick; 18 | import rx.Observable; 19 | import rx.Subscriber; 20 | import rx.Subscription; 21 | import rx.android.schedulers.AndroidSchedulers; 22 | import rx.functions.Action1; 23 | import rx.functions.Func1; 24 | import rx.schedulers.Schedulers; 25 | import rx.subscriptions.CompositeSubscription; 26 | 27 | 28 | public class Operators2Fragment extends Fragment { 29 | 30 | 31 | static final String TAG = "Operators2Fragment"; 32 | @BindView(R.id.btn_buffer) 33 | Button mBtnBuffer; 34 | @BindView(R.id.btn_flarmap) 35 | Button mBtnFlarmap; 36 | @BindView(R.id.btn_concatmap) 37 | Button mBtnConcatmap; 38 | @BindView(R.id.btn_switchmap) 39 | Button mBtnSwitchmap; 40 | 41 | 42 | private CompositeSubscription mCompositeSubscription; 43 | Subscription mSubscription; 44 | 45 | @Override 46 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 47 | Bundle savedInstanceState) { 48 | View view = inflater.inflate(R.layout.operators2_fragment, container, false); 49 | ButterKnife.bind(this, view); 50 | mCompositeSubscription = new CompositeSubscription(); 51 | return view; 52 | } 53 | 54 | @Override 55 | public void onResume() { 56 | super.onResume(); 57 | } 58 | 59 | @Override 60 | public void onViewCreated(View view, Bundle savedInstanceState) { 61 | super.onViewCreated(view, savedInstanceState); 62 | 63 | } 64 | 65 | 66 | 67 | @OnClick({R.id.btn_buffer, R.id.btn_flarmap, R.id.btn_concatmap, R.id.btn_switchmap}) 68 | public void onClick(View view) { 69 | switch (view.getId()) { 70 | case R.id.btn_buffer: 71 | doBufferOperation(); 72 | break; 73 | case R.id.btn_flarmap: 74 | doflatMap(); 75 | break; 76 | case R.id.btn_concatmap: 77 | doConcatmap(); 78 | break; 79 | case R.id.btn_switchmap: 80 | doSwitchmap(); 81 | break; 82 | } 83 | } 84 | 85 | private void doSwitchmap() { 86 | Observable.just(10, 20, 30).switchMap(new Func1>() { 87 | @Override 88 | public Observable call(Integer integer) { 89 | //10的延迟执行时间为200毫秒、20和30的延迟执行时间为180毫秒 90 | int delay = 200; 91 | if (integer > 10) 92 | delay = 180; 93 | 94 | return Observable.from(new Integer[]{integer, integer / 2}).delay(delay, TimeUnit.MILLISECONDS); 95 | } 96 | }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1() { 97 | @Override 98 | public void call(Integer integer) { 99 | printLog("Switch Next"+integer); 100 | } 101 | }); 102 | } 103 | 104 | //与flatmap大致相同,只是产生的顺序不同; 105 | private void doConcatmap() { 106 | Observable.just(10, 20, 30).concatMap(new Func1>() { 107 | @Override 108 | public Observable call(Integer integer) { 109 | //10的延迟执行时间为200毫秒、20和30的延迟执行时间为180毫秒 110 | int delay = 200; 111 | if (integer > 10) 112 | delay = 180; 113 | 114 | return Observable.from(new Integer[]{integer, integer / 2}).delay(delay, TimeUnit.MILLISECONDS); 115 | } 116 | }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1() { 117 | @Override 118 | public void call(Integer integer) { 119 | printLog("Concat Next"+integer); 120 | } 121 | }); 122 | 123 | } 124 | 125 | //与map一样,都是对数据转化,map是一对一,flatmap一对多; 126 | private void doflatMap() { 127 | Bean bean=new Bean(); 128 | Observable.just(bean) 129 | .flatMap(new Func1>() { 130 | @Override 131 | public Observable call(Bean bean) { 132 | return Observable.from(bean.getData()); 133 | } 134 | 135 | }) 136 | .subscribe(new Action1() { 137 | @Override 138 | public void call(String s) { 139 | printLog("Flat Next"+s); 140 | } 141 | }); 142 | 143 | } 144 | 145 | //一共发送10次信息,Observable每次缓存3秒一起发送 146 | private void doBufferOperation() { 147 | mSubscription=Observable.create(new Observable.OnSubscribe() { 148 | @Override 149 | public void call(Subscriber subscriber) { 150 | for (int i = 0; i <10 ; i++) { 151 | subscriber.onNext(" "+i); 152 | try { 153 | Thread.sleep(1000); 154 | } catch (InterruptedException e) { 155 | e.printStackTrace(); 156 | } 157 | } 158 | } 159 | }).subscribeOn(Schedulers.io()) 160 | .buffer(3,TimeUnit.SECONDS) 161 | .subscribe(new Action1>() { 162 | @Override 163 | public void call(List list) { 164 | printLog("接收到 "+list.size()+"次"); 165 | for (int i = 0; i < list.size(); i++){ 166 | printLog(list.get(i)); 167 | } 168 | 169 | } 170 | }); 171 | mCompositeSubscription.add(mSubscription); 172 | 173 | 174 | } 175 | 176 | private class Bean{ 177 | String[] data={"1","2","3"}; 178 | 179 | public String[] getData(){ 180 | return data; 181 | } 182 | } 183 | 184 | 185 | private void printLog(String s) { 186 | Log.i(TAG, s); 187 | } 188 | 189 | @Override 190 | public void onDestroy() { 191 | super.onDestroy(); 192 | mCompositeSubscription.unsubscribe(); 193 | } 194 | } 195 | 196 | 197 | 198 | 199 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/PollingActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package com.demo.maat.hello_rxjava; 19 | 20 | import android.os.Bundle; 21 | import android.support.v4.app.FragmentTransaction; 22 | 23 | import com.demo.maat.hello_rxjava.common.activities.SampleActivityBase; 24 | import com.demo.maat.hello_rxjava.common.logger.Log; 25 | import com.demo.maat.hello_rxjava.common.logger.LogFragment; 26 | import com.demo.maat.hello_rxjava.common.logger.LogWrapper; 27 | import com.demo.maat.hello_rxjava.common.logger.MessageOnlyLogFilter; 28 | 29 | 30 | public class PollingActivity extends SampleActivityBase { 31 | 32 | public static final String TAG = "PollingActivity"; 33 | 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.polling_activity_main); 39 | 40 | if (savedInstanceState == null) { 41 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 42 | PollingFragment fragment = new PollingFragment(); 43 | transaction.replace(R.id.sample_content_fragment, fragment); 44 | transaction.commit(); 45 | } 46 | } 47 | 48 | 49 | 50 | 51 | @Override 52 | public void initializeLogging() { 53 | LogWrapper logWrapper = new LogWrapper(); 54 | Log.setLogNode(logWrapper); 55 | 56 | MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter(); 57 | logWrapper.setNext(msgFilter); 58 | 59 | // On screen logging via a fragment with a TextView. 60 | LogFragment logFragment = (LogFragment) getSupportFragmentManager() 61 | .findFragmentById(R.id.log_fragment); 62 | msgFilter.setNext(logFragment.getLogView()); 63 | 64 | Log.i(TAG, "Ready"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/PollingFragment.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.Button; 9 | 10 | import com.demo.maat.hello_rxjava.common.logger.Log; 11 | 12 | import java.util.concurrent.TimeUnit; 13 | 14 | import butterknife.BindView; 15 | import butterknife.ButterKnife; 16 | import butterknife.OnClick; 17 | import rx.Observable; 18 | import rx.Subscriber; 19 | import rx.Subscription; 20 | import rx.functions.Action0; 21 | import rx.functions.Action1; 22 | import rx.schedulers.Schedulers; 23 | import rx.subscriptions.CompositeSubscription; 24 | 25 | 26 | public class PollingFragment extends Fragment { 27 | 28 | 29 | static final String TAG = "PollingFragment"; 30 | @BindView(R.id.btn_polling) 31 | Button mBtnPolling; 32 | 33 | int N=0; 34 | private Subscription subscribe; 35 | private CompositeSubscription mCompositeSubscription; 36 | 37 | @Override 38 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 39 | Bundle savedInstanceState) { 40 | View view = inflater.inflate(R.layout.polling_fragment, container, false); 41 | ButterKnife.bind(this, view); 42 | mCompositeSubscription = new CompositeSubscription(); 43 | return view; 44 | } 45 | 46 | @Override 47 | public void onResume() { 48 | super.onResume(); 49 | } 50 | 51 | @Override 52 | public void onViewCreated(View view, Bundle savedInstanceState) { 53 | super.onViewCreated(view, savedInstanceState); 54 | 55 | } 56 | 57 | 58 | @OnClick(R.id.btn_polling) 59 | public void onClick() { 60 | 61 | //此处有bug,subscribe无法释放,望高人pull requests 62 | subscribe=Observable.create(new Observable.OnSubscribe() { 63 | @Override 64 | public void call(final Subscriber observer) { 65 | 66 | Schedulers.newThread().createWorker() 67 | .schedulePeriodically(new Action0() { 68 | @Override 69 | public void call() { 70 | observer.onNext(" "+(N++)); 71 | } 72 | }, 0, 1000, TimeUnit.MILLISECONDS); 73 | } 74 | }) 75 | .subscribe(new Action1() { 76 | @Override 77 | public void call(String s) { 78 | printLog("polling"+s); 79 | } 80 | }); 81 | mCompositeSubscription.add(subscribe); 82 | } 83 | private void printLog(String s) { 84 | Log.i(TAG, s); 85 | } 86 | 87 | @Override 88 | public void onDestroy() { 89 | super.onDestroy(); 90 | mCompositeSubscription.unsubscribe(); 91 | } 92 | 93 | 94 | } 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/RxAndroidActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package com.demo.maat.hello_rxjava; 19 | 20 | import android.os.Bundle; 21 | import android.support.v4.app.FragmentTransaction; 22 | 23 | import com.demo.maat.hello_rxjava.common.activities.SampleActivityBase; 24 | import com.demo.maat.hello_rxjava.common.logger.Log; 25 | import com.demo.maat.hello_rxjava.common.logger.LogFragment; 26 | import com.demo.maat.hello_rxjava.common.logger.LogWrapper; 27 | import com.demo.maat.hello_rxjava.common.logger.MessageOnlyLogFilter; 28 | 29 | 30 | public class RxAndroidActivity extends SampleActivityBase { 31 | 32 | public static final String TAG = "RxAndroidActivity"; 33 | 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.scheduler_activity_main); 39 | 40 | if (savedInstanceState == null) { 41 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 42 | RxAndroidFragment fragment = new RxAndroidFragment(); 43 | transaction.replace(R.id.sample_content_fragment, fragment); 44 | transaction.commit(); 45 | } 46 | } 47 | 48 | 49 | 50 | 51 | @Override 52 | public void initializeLogging() { 53 | LogWrapper logWrapper = new LogWrapper(); 54 | Log.setLogNode(logWrapper); 55 | 56 | MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter(); 57 | logWrapper.setNext(msgFilter); 58 | 59 | // On screen logging via a fragment with a TextView. 60 | LogFragment logFragment = (LogFragment) getSupportFragmentManager() 61 | .findFragmentById(R.id.log_fragment); 62 | msgFilter.setNext(logFragment.getLogView()); 63 | 64 | Log.i(TAG, "Ready"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/RxAndroidFragment.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava; 2 | 3 | import android.os.Bundle; 4 | import android.os.HandlerThread; 5 | import android.os.Looper; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.Button; 11 | import android.widget.ProgressBar; 12 | 13 | import com.demo.maat.hello_rxjava.common.logger.Log; 14 | 15 | import java.util.concurrent.TimeUnit; 16 | 17 | import butterknife.BindView; 18 | import butterknife.ButterKnife; 19 | import butterknife.OnClick; 20 | import rx.Observable; 21 | import rx.Subscriber; 22 | import rx.Subscription; 23 | import rx.android.schedulers.AndroidSchedulers; 24 | import rx.exceptions.OnErrorThrowable; 25 | import rx.functions.Func0; 26 | import rx.subscriptions.CompositeSubscription; 27 | 28 | import static android.os.Process.THREAD_PRIORITY_BACKGROUND; 29 | 30 | 31 | public class RxAndroidFragment extends Fragment { 32 | 33 | 34 | static final String TAG = "RxAndroidFragment"; 35 | @BindView(R.id.btn_rxandroid) 36 | Button mBtnPolling; 37 | @BindView(R.id.progress_operation_two_running) 38 | ProgressBar mProgressOperationTwoRunning; 39 | 40 | private Looper backgroundLooper; 41 | 42 | 43 | private Subscription subscribe; 44 | private CompositeSubscription mCompositeSubscription; 45 | 46 | 47 | @Override 48 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 49 | Bundle savedInstanceState) { 50 | View view = inflater.inflate(R.layout.rxandroid_fragment, container, false); 51 | ButterKnife.bind(this, view); 52 | mCompositeSubscription = new CompositeSubscription(); 53 | 54 | BackgroundThread backgroundThread = new BackgroundThread(); 55 | backgroundThread.start(); 56 | backgroundLooper = backgroundThread.getLooper(); 57 | 58 | return view; 59 | } 60 | 61 | 62 | @OnClick(R.id.btn_rxandroid) 63 | public void onClick() { 64 | onRunSchedulerExampleButtonClicked(); 65 | } 66 | 67 | void onRunSchedulerExampleButtonClicked() { 68 | 69 | sampleObservable() 70 | // Run on a background thread 71 | .subscribeOn(AndroidSchedulers.from(backgroundLooper)) 72 | // Be notified on the main thread 73 | .observeOn(AndroidSchedulers.mainThread()) 74 | .subscribe(new Subscriber() { 75 | @Override 76 | public void onCompleted() { 77 | printLog("Completed"); 78 | mProgressOperationTwoRunning.setVisibility(View.INVISIBLE); 79 | } 80 | 81 | @Override 82 | public void onError(Throwable e) { 83 | printLog("Error"); 84 | mProgressOperationTwoRunning.setVisibility(View.INVISIBLE); 85 | } 86 | 87 | @Override 88 | public void onNext(String string) { 89 | mProgressOperationTwoRunning.setVisibility(View.INVISIBLE); 90 | printLog("Next " + string); 91 | } 92 | }); 93 | } 94 | 95 | Observable sampleObservable() { 96 | mProgressOperationTwoRunning.setVisibility(View.VISIBLE); 97 | 98 | return Observable.defer(new Func0>() { 99 | @Override 100 | public Observable call() { 101 | try { 102 | // Do some long running operation 103 | Thread.sleep(TimeUnit.SECONDS.toMillis(5)); 104 | } catch (InterruptedException e) { 105 | throw OnErrorThrowable.from(e); 106 | } 107 | return Observable.just("one", "two", "three", "four", "five"); 108 | } 109 | }); 110 | } 111 | 112 | private void printLog(String s) { 113 | Log.i(TAG, s); 114 | } 115 | 116 | @Override 117 | public void onDestroy() { 118 | super.onDestroy(); 119 | mCompositeSubscription.unsubscribe(); 120 | } 121 | 122 | 123 | static class BackgroundThread extends HandlerThread { 124 | BackgroundThread() { 125 | super("SchedulerSample-BackgroundThread", THREAD_PRIORITY_BACKGROUND); 126 | } 127 | } 128 | } 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/RxJavaMainActivity.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | import android.widget.Button; 8 | 9 | import butterknife.BindView; 10 | import butterknife.ButterKnife; 11 | import butterknife.OnClick; 12 | 13 | public class RxJavaMainActivity extends AppCompatActivity { 14 | 15 | 16 | @BindView(R.id.btn_scheduler) 17 | Button mBtnScheduler; 18 | @BindView(R.id.btn_operators1) 19 | Button mBtnOperators1; 20 | @BindView(R.id.btn_operators2) 21 | Button mBtnOperators2; 22 | @BindView(R.id.btn_operators3) 23 | Button mBtnOperators3; 24 | @BindView(R.id.btn_operators4) 25 | Button mBtnOperators4; 26 | 27 | 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | setContentView(R.layout.rxjava_activity_main); 32 | ButterKnife.bind(this); 33 | } 34 | 35 | 36 | 37 | 38 | @OnClick({R.id.btn_scheduler,R.id.btn_operators1, R.id.btn_operators2, R.id.btn_operators3, R.id.btn_operators4, R.id.activity_main}) 39 | public void onClick(View view) { 40 | switch (view.getId()) { 41 | case R.id.btn_scheduler: 42 | Intent intent = new Intent(this, SchedulerActivity.class); 43 | startActivity(intent); 44 | break; 45 | case R.id.btn_operators1: 46 | Intent operator1 = new Intent(this, Operators1Activity.class); 47 | startActivity(operator1); 48 | break; 49 | case R.id.btn_operators2: 50 | Intent operator2 = new Intent(this, Operators2Activity.class); 51 | startActivity(operator2); 52 | break; 53 | case R.id.btn_operators3: 54 | Intent polling = new Intent(this, PollingActivity.class); 55 | startActivity(polling); 56 | break; 57 | case R.id.btn_operators4: 58 | Intent debounce = new Intent(this, DebounceEditTextActivity.class); 59 | startActivity(debounce); 60 | break; 61 | 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/RxJavaRetrofitActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package com.demo.maat.hello_rxjava; 19 | 20 | import android.os.Bundle; 21 | import android.support.v4.app.FragmentTransaction; 22 | 23 | import com.demo.maat.hello_rxjava.common.activities.SampleActivityBase; 24 | import com.demo.maat.hello_rxjava.common.logger.Log; 25 | import com.demo.maat.hello_rxjava.common.logger.LogFragment; 26 | import com.demo.maat.hello_rxjava.common.logger.LogWrapper; 27 | import com.demo.maat.hello_rxjava.common.logger.MessageOnlyLogFilter; 28 | 29 | 30 | public class RxJavaRetrofitActivity extends SampleActivityBase { 31 | 32 | public static final String TAG = "RxJavaRetrofitActivity"; 33 | 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.scheduler_activity_main); 39 | 40 | if (savedInstanceState == null) { 41 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 42 | RxJavaRetrofitFragment fragment = new RxJavaRetrofitFragment(); 43 | transaction.replace(R.id.sample_content_fragment, fragment); 44 | transaction.commit(); 45 | } 46 | } 47 | 48 | 49 | 50 | 51 | @Override 52 | public void initializeLogging() { 53 | LogWrapper logWrapper = new LogWrapper(); 54 | Log.setLogNode(logWrapper); 55 | 56 | MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter(); 57 | logWrapper.setNext(msgFilter); 58 | 59 | // On screen logging via a fragment with a TextView. 60 | LogFragment logFragment = (LogFragment) getSupportFragmentManager() 61 | .findFragmentById(R.id.log_fragment); 62 | msgFilter.setNext(logFragment.getLogView()); 63 | 64 | Log.i(TAG, "Ready"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/RxJavaRetrofitFragment.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.Button; 9 | 10 | import com.demo.maat.hello_rxjava.common.logger.Log; 11 | import com.demo.maat.hello_rxjava.retrofit.zhihu.ZhihuDaily; 12 | import com.demo.maat.hello_rxjava.retrofit.zhihu.ZhihuDailyItem; 13 | import com.demo.maat.hello_rxjava.retrofit.zhihu.ZhihuManager; 14 | 15 | import butterknife.BindView; 16 | import butterknife.ButterKnife; 17 | import butterknife.OnClick; 18 | import rx.Subscriber; 19 | import rx.Subscription; 20 | import rx.android.schedulers.AndroidSchedulers; 21 | import rx.schedulers.Schedulers; 22 | import rx.subscriptions.CompositeSubscription; 23 | 24 | 25 | public class RxJavaRetrofitFragment extends Fragment { 26 | 27 | 28 | static final String TAG = "RxJavaRetrofitFragment"; 29 | @BindView(R.id.btn_get) 30 | Button mBtnGet; 31 | private Subscription subscription; 32 | 33 | private CompositeSubscription mCompositeSubscription; 34 | ; 35 | 36 | @Override 37 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 38 | Bundle savedInstanceState) { 39 | View view = inflater.inflate(R.layout.retrofit_fragment, container, false); 40 | ButterKnife.bind(this, view); 41 | mCompositeSubscription = new CompositeSubscription(); 42 | return view; 43 | } 44 | 45 | @Override 46 | public void onResume() { 47 | super.onResume(); 48 | } 49 | 50 | @Override 51 | public void onViewCreated(View view, Bundle savedInstanceState) { 52 | super.onViewCreated(view, savedInstanceState); 53 | 54 | } 55 | @OnClick(R.id.btn_get) 56 | public void onClick() { 57 | 58 | subscription= ZhihuManager.getInstance() 59 | .getZhihuApiService() 60 | .getLastDaily() 61 | .subscribeOn(Schedulers.io()) 62 | .observeOn(AndroidSchedulers.mainThread()) 63 | .subscribe(new Subscriber() { 64 | @Override 65 | public void onCompleted() { 66 | 67 | } 68 | 69 | @Override 70 | public void onError(Throwable e) { 71 | 72 | } 73 | 74 | @Override 75 | public void onNext(ZhihuDaily daily) { 76 | //get first bean 77 | ZhihuDailyItem item=daily.getStories().get(0); 78 | printLog("Title:"+item.getTitle()); 79 | printLog("Data: "+item.getDate()); 80 | printLog("Id: "+item.getId()); 81 | printLog("Type: "+item.getType()); 82 | 83 | 84 | } 85 | }); 86 | mCompositeSubscription.add(subscription); 87 | 88 | } 89 | 90 | private void printLog(String s) { 91 | Log.i(TAG, s ); 92 | } 93 | 94 | 95 | 96 | @Override 97 | public void onDestroy() { 98 | super.onDestroy(); 99 | mCompositeSubscription.unsubscribe(); 100 | } 101 | 102 | 103 | 104 | } 105 | 106 | 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/SchedulerActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package com.demo.maat.hello_rxjava; 19 | 20 | import android.os.Bundle; 21 | import android.support.v4.app.FragmentTransaction; 22 | 23 | import com.demo.maat.hello_rxjava.common.activities.SampleActivityBase; 24 | import com.demo.maat.hello_rxjava.common.logger.Log; 25 | import com.demo.maat.hello_rxjava.common.logger.LogFragment; 26 | import com.demo.maat.hello_rxjava.common.logger.LogWrapper; 27 | import com.demo.maat.hello_rxjava.common.logger.MessageOnlyLogFilter; 28 | 29 | 30 | public class SchedulerActivity extends SampleActivityBase { 31 | 32 | public static final String TAG = "SchedulerActivity"; 33 | 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.scheduler_activity_main); 39 | 40 | if (savedInstanceState == null) { 41 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 42 | SchedulerFragment fragment = new SchedulerFragment(); 43 | transaction.replace(R.id.sample_content_fragment, fragment); 44 | transaction.commit(); 45 | } 46 | } 47 | 48 | 49 | 50 | 51 | @Override 52 | public void initializeLogging() { 53 | LogWrapper logWrapper = new LogWrapper(); 54 | Log.setLogNode(logWrapper); 55 | 56 | MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter(); 57 | logWrapper.setNext(msgFilter); 58 | 59 | // On screen logging via a fragment with a TextView. 60 | LogFragment logFragment = (LogFragment) getSupportFragmentManager() 61 | .findFragmentById(R.id.log_fragment); 62 | msgFilter.setNext(logFragment.getLogView()); 63 | 64 | Log.i(TAG, "Ready"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/SchedulerFragment.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava; 2 | 3 | import android.os.Bundle; 4 | import android.os.Looper; 5 | import android.support.v4.app.Fragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.Button; 10 | import android.widget.ProgressBar; 11 | 12 | import com.demo.maat.hello_rxjava.common.logger.Log; 13 | 14 | import butterknife.BindView; 15 | import butterknife.ButterKnife; 16 | import butterknife.OnClick; 17 | import rx.Observable; 18 | import rx.Subscriber; 19 | import rx.Subscription; 20 | import rx.android.schedulers.AndroidSchedulers; 21 | import rx.functions.Func1; 22 | import rx.schedulers.Schedulers; 23 | import rx.subscriptions.CompositeSubscription; 24 | 25 | 26 | public class SchedulerFragment extends Fragment { 27 | 28 | 29 | static final String TAG = "SchedulerFragment"; 30 | 31 | String[] data = {"1", "2", "3"}; 32 | @BindView(R.id.btn_no_map) 33 | Button mBtnNoMap; 34 | @BindView(R.id.btn_just) 35 | Button mBtnJust; 36 | @BindView(R.id.btn_just_one) 37 | Button mBtnJustone; 38 | @BindView(R.id.btn_just_two) 39 | Button mBtnJusttwo; 40 | @BindView(R.id.btn_just_three) 41 | Button mBtnJustthree; 42 | @BindView(R.id.btn_just_four) 43 | Button mBtnJustfour; 44 | @BindView(R.id.btn_just_five) 45 | Button mBtnJustfive; 46 | @BindView(R.id.btn_just_six) 47 | Button mBtnJustsix; 48 | @BindView(R.id.btn_one_map) 49 | Button mBtnOneMap; 50 | @BindView(R.id.btn_two_map) 51 | Button mBtnTwoMap; 52 | @BindView(R.id.btn_long_operation) 53 | Button mBtnLongOperation; 54 | @BindView(R.id.progress_operation_running) 55 | ProgressBar mProgressOperationRunning; 56 | @BindView(R.id.progress_operation_two_running) 57 | ProgressBar mProgressOperationTwoRunning; 58 | private Subscription baseSubscription; 59 | private Subscription oneMapSubscription; 60 | private Subscription twoMapSubscription; 61 | private Subscription longOpeSubscription; 62 | private CompositeSubscription mCompositeSubscription; 63 | ; 64 | 65 | @Override 66 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 67 | Bundle savedInstanceState) { 68 | View view = inflater.inflate(R.layout.scheduler_fragment, container, false); 69 | ButterKnife.bind(this, view); 70 | mCompositeSubscription = new CompositeSubscription(); 71 | return view; 72 | } 73 | 74 | @Override 75 | public void onResume() { 76 | super.onResume(); 77 | } 78 | 79 | @Override 80 | public void onViewCreated(View view, Bundle savedInstanceState) { 81 | super.onViewCreated(view, savedInstanceState); 82 | 83 | } 84 | 85 | 86 | @OnClick({R.id.btn_just, R.id.btn_just_one, R.id.btn_just_two, 87 | R.id.btn_just_three,R.id.btn_just_four, R.id.btn_just_five, 88 | R.id.btn_just_six,R.id.btn_no_map, R.id.btn_one_map, R.id.btn_two_map, R.id.btn_long_operation}) 89 | public void onClick(View view) { 90 | switch (view.getId()) { 91 | case R.id.btn_just: 92 | doJust(); 93 | break; 94 | case R.id.btn_just_one: 95 | doJustOne(); 96 | break; 97 | case R.id.btn_just_two: 98 | doJustTwo(); 99 | break; 100 | case R.id.btn_just_three: 101 | doJustThree(); 102 | break; 103 | case R.id.btn_just_four: 104 | doJustFour(); 105 | break; 106 | case R.id.btn_just_five: 107 | doJustFive(); 108 | break; 109 | case R.id.btn_just_six: 110 | doJustSix(); 111 | break; 112 | case R.id.btn_no_map: 113 | doBaseOperation(); 114 | break; 115 | case R.id.btn_one_map: 116 | doOnemapOperation(); 117 | break; 118 | case R.id.btn_long_operation: 119 | doLongOperation(); 120 | break; 121 | case R.id.btn_two_map: 122 | doTwomapWithLongOperation(); 123 | break; 124 | } 125 | } 126 | 127 | 128 | 129 | private void doJust() { 130 | Observable.just(1, 2, 3) 131 | .subscribe(new Subscriber() { 132 | @Override 133 | public void onCompleted() { 134 | printLog("Completed"); 135 | } 136 | 137 | @Override 138 | public void onError(Throwable e) { 139 | printLog("onError"); 140 | 141 | } 142 | 143 | @Override 144 | public void onNext(Integer integer) { 145 | printLog("Next " + integer + " "); 146 | } 147 | }); 148 | } 149 | 150 | 151 | 152 | 153 | 154 | 155 | private void doJustOne() { 156 | Observable.just(1, 2, 3) 157 | .subscribeOn(Schedulers.io()) 158 | .subscribe(new Subscriber() { 159 | @Override 160 | public void onCompleted() { 161 | printLog("Completed"); 162 | } 163 | 164 | @Override 165 | public void onError(Throwable e) { 166 | printLog("onError"); 167 | 168 | } 169 | 170 | @Override 171 | public void onNext(Integer integer) { 172 | printLog("Next " + integer + " "); 173 | } 174 | }); 175 | } 176 | 177 | 178 | 179 | 180 | private void doJustTwo() { 181 | Observable.just(1, 2, 3) 182 | .subscribeOn(Schedulers.io()) 183 | .observeOn(AndroidSchedulers.mainThread()) 184 | .subscribe(new Subscriber() { 185 | @Override 186 | public void onCompleted() { 187 | printLog("Completed"); 188 | } 189 | 190 | @Override 191 | public void onError(Throwable e) { 192 | printLog("onError"); 193 | 194 | } 195 | 196 | @Override 197 | public void onNext(Integer integer) { 198 | printLog("Next " + integer + " "); 199 | } 200 | }); 201 | } 202 | 203 | 204 | 205 | 206 | 207 | private void doJustThree() { 208 | Observable.just(1, 2, 3) 209 | .subscribeOn(Schedulers.io()) 210 | .map(new Func1() { 211 | @Override 212 | public String call(Integer integer) { 213 | printLog("map "+integer+"a"); 214 | return integer+"a"; 215 | } 216 | }) 217 | .subscribe(new Subscriber() { 218 | @Override 219 | public void onCompleted() { 220 | printLog("Completed"); 221 | } 222 | 223 | @Override 224 | public void onError(Throwable e) { 225 | printLog("onError"); 226 | 227 | } 228 | 229 | @Override 230 | public void onNext(String s) { 231 | printLog("Next " +s); 232 | 233 | } 234 | 235 | }); 236 | } 237 | private void doJustFour() { 238 | Observable.just(1, 2, 3) 239 | .subscribeOn(Schedulers.io()) 240 | .map(new Func1() { 241 | @Override 242 | public String call(Integer integer) { 243 | printLog("map1 "+integer+"a"); 244 | return integer+"a"; 245 | } 246 | }) 247 | .observeOn(AndroidSchedulers.mainThread()) 248 | .map(new Func1() { 249 | @Override 250 | public String call(String s) { 251 | printLog("map2 "+s+"b "); 252 | return s+"b"; 253 | } 254 | }) 255 | .subscribe(new Subscriber() { 256 | @Override 257 | public void onCompleted() { 258 | printLog("Completed"); 259 | } 260 | 261 | @Override 262 | public void onError(Throwable e) { 263 | printLog("onError"); 264 | 265 | } 266 | 267 | @Override 268 | public void onNext(String s) { 269 | printLog("Next " +s); 270 | 271 | } 272 | 273 | }); 274 | } 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | private void doJustFive() { 286 | Observable.just(1, 2, 3) 287 | .subscribeOn(Schedulers.io()) 288 | .map(new Func1() { 289 | @Override 290 | public String call(Integer integer) { 291 | printLog("map1 "+integer+"a"); 292 | return integer+"a"; 293 | } 294 | }) 295 | .observeOn(AndroidSchedulers.mainThread()) 296 | .map(new Func1() { 297 | @Override 298 | public String call(String s) { 299 | printLog("map2 "+s+"b "); 300 | return s+"b"; 301 | } 302 | }) 303 | .observeOn(Schedulers.io()) 304 | .map(new Func1() { 305 | @Override 306 | public String call(String s) { 307 | printLog("map3 "+s+"c "); 308 | return s+"c"; 309 | } 310 | }) 311 | .observeOn(AndroidSchedulers.mainThread()) 312 | .subscribe(new Subscriber() { 313 | @Override 314 | public void onCompleted() { 315 | printLog("Completed"); 316 | } 317 | 318 | @Override 319 | public void onError(Throwable e) { 320 | printLog("onError"); 321 | 322 | } 323 | 324 | @Override 325 | public void onNext(String s) { 326 | printLog("Next " +s); 327 | 328 | } 329 | 330 | }); 331 | } 332 | 333 | 334 | 335 | 336 | 337 | private void doJustSix() { 338 | Observable.just(1, 2, 3) 339 | .subscribeOn(AndroidSchedulers.mainThread()) 340 | .map(new Func1() { 341 | @Override 342 | public String call(Integer integer) { 343 | printLog("map1 "+integer+"a"); 344 | return integer+"a"; 345 | } 346 | }) 347 | .observeOn(Schedulers.io()) 348 | .map(new Func1() { 349 | @Override 350 | public String call(String s) { 351 | printLog("map2 "+s+"b "); 352 | return s+"b"; 353 | } 354 | }) 355 | .observeOn(AndroidSchedulers.mainThread()) 356 | .map(new Func1() { 357 | @Override 358 | public String call(String s) { 359 | printLog("map3 "+s+"c "); 360 | return s+"c"; 361 | } 362 | }) 363 | .subscribeOn(Schedulers.io()) 364 | .observeOn(Schedulers.io()) 365 | .subscribe(new Subscriber() { 366 | @Override 367 | public void onCompleted() { 368 | printLog("Completed"); 369 | } 370 | @Override 371 | public void onError(Throwable e) { 372 | printLog("onError"); 373 | 374 | } 375 | @Override 376 | public void onNext(String s) { 377 | printLog("Next " +s); 378 | 379 | } 380 | 381 | }); 382 | } 383 | 384 | 385 | /** 386 | * Subscriber加Onsubscribe基本使用,没有线程切换,没有过滤等操作 387 | * 388 | */ 389 | 390 | private void doBaseOperation() { 391 | baseSubscription = Observable.create(new Observable.OnSubscribe() { 392 | @Override 393 | public void call(Subscriber subscriber) { 394 | printLog("onStart in OnSubscribe"); 395 | subscriber.onStart(); 396 | int N = data.length; 397 | for (int i = 0; i < N; i++) { 398 | printLog("onNext " + data[i] + " in OnSubscribe"); 399 | subscriber.onNext(data[i]); 400 | 401 | } 402 | printLog("OnCompleted in OnSubscribe"); 403 | subscriber.onCompleted(); 404 | 405 | } 406 | }).subscribe(new Subscriber() { 407 | @Override 408 | public void onCompleted() { 409 | printLog("OnCompleted in Subscriber"); 410 | 411 | 412 | } 413 | 414 | @Override 415 | public void onError(Throwable e) { 416 | printLog("onError in Subscriber"); 417 | 418 | } 419 | 420 | @Override 421 | public void onNext(String s) { 422 | printLog("onNext " + s + " in Subscriber"); 423 | 424 | } 425 | }); 426 | mCompositeSubscription.add(baseSubscription); 427 | 428 | } 429 | 430 | /** 431 | * 对数据做一次map操作,给每一个数据后面加一个"a",没有线程调度; 432 | */ 433 | private void doOnemapOperation() { 434 | oneMapSubscription = Observable.create(new Observable.OnSubscribe() { 435 | @Override 436 | public void call(Subscriber subscriber) { 437 | printLog("onStart in OnSubscribe"); 438 | subscriber.onStart(); 439 | int N = data.length; 440 | for (int i = 0; i < N; i++) { 441 | printLog("onNext " + data[i] + " in OnSubscribe"); 442 | subscriber.onNext(data[i]); 443 | } 444 | printLog("OnCompleted in OnSubscribe"); 445 | subscriber.onCompleted(); 446 | 447 | } 448 | }).map(new Func1() { 449 | @Override 450 | public String call(String s) { 451 | String result = s + "a"; 452 | printLog(result); 453 | return result; 454 | } 455 | }).subscribe(new Subscriber() { 456 | @Override 457 | public void onCompleted() { 458 | printLog("OnCompleted in Subscriber"); 459 | 460 | 461 | } 462 | 463 | @Override 464 | public void onError(Throwable e) { 465 | printLog("onError in Subscriber"); 466 | 467 | } 468 | 469 | @Override 470 | public void onNext(String s) { 471 | printLog("onNext " + s + " in Subscriber"); 472 | 473 | } 474 | }); 475 | mCompositeSubscription.add(oneMapSubscription); 476 | } 477 | 478 | 479 | /** 480 | * 模拟阻操作,如网络请求,文件读取,再加上scheduler,切换线程。 481 | */ 482 | private void doLongOperation() { 483 | mProgressOperationRunning.setVisibility(View.VISIBLE); 484 | longOpeSubscription = Observable.create(new Observable.OnSubscribe() { 485 | @Override 486 | public void call(Subscriber subscriber) { 487 | printLog("onStart in OnSubscribe"); 488 | subscriber.onStart(); 489 | int N = data.length; 490 | for (int i = 0; i < N; i++) { 491 | dosomethingBlockThread(); 492 | printLog("onNext" + data[i] + " in OnSubscribe"); 493 | subscriber.onNext(data[i]); 494 | 495 | } 496 | printLog("OnCompleted in OnSubscribe"); 497 | subscriber.onCompleted(); 498 | } 499 | }).subscribeOn(Schedulers.io()) 500 | .observeOn(AndroidSchedulers.mainThread()) 501 | .subscribe(new Subscriber() { 502 | @Override 503 | public void onCompleted() { 504 | printLog("OnCompleted in Subscriber"); 505 | mProgressOperationRunning.setVisibility(View.INVISIBLE); 506 | } 507 | 508 | @Override 509 | public void onError(Throwable e) { 510 | printLog("onError in Subscriber"); 511 | mProgressOperationRunning.setVisibility(View.INVISIBLE); 512 | 513 | } 514 | 515 | @Override 516 | public void onNext(String s) { 517 | printLog("onNext " + s + " in Subscriber"); 518 | 519 | } 520 | }); 521 | mCompositeSubscription.add(longOpeSubscription); 522 | } 523 | 524 | /** 525 | * 对数据进行两次map操作并加上线程调度,第一次map操作每个数据后面+"a",第二次map操作每个数据后面+"b". 526 | */ 527 | private void doTwomapWithLongOperation() { 528 | mProgressOperationTwoRunning.setVisibility(View.VISIBLE); 529 | twoMapSubscription = Observable.create(new Observable.OnSubscribe() { 530 | @Override 531 | public void call(Subscriber subscriber) { 532 | printLog("onStart in OnSubscribe"); 533 | subscriber.onStart(); 534 | int N = data.length; 535 | for (int i = 0; i < N; i++) { 536 | dosomethingBlockThread(); 537 | printLog("onNext " + data[i] + " in OnSubscribe"); 538 | subscriber.onNext(data[i]); 539 | 540 | } 541 | printLog("OnCompleted in OnSubscribe"); 542 | subscriber.onCompleted(); 543 | } 544 | }).subscribeOn(Schedulers.io()) 545 | .observeOn(Schedulers.newThread()) 546 | .map(new Func1() { 547 | @Override 548 | public String call(String s) { 549 | String result = s + "a"; 550 | printLog("Map1 " + result); 551 | return result; 552 | } 553 | }) 554 | .observeOn(AndroidSchedulers.mainThread()) 555 | .map(new Func1() { 556 | @Override 557 | public String call(String s) { 558 | String result = s + "b"; 559 | printLog("Map2 " + result); 560 | return result; 561 | } 562 | }) 563 | // 你可以把上面的注释了,使用这个.observeOn(AndroidSchedulers.mainThread())看看map2有什么变化 564 | // .observeOn(AndroidSchedulers.mainThread()) 565 | .subscribe(new Subscriber() { 566 | @Override 567 | public void onCompleted() { 568 | printLog("OnCompleted in Subscriber"); 569 | mProgressOperationTwoRunning.setVisibility(View.INVISIBLE); 570 | } 571 | 572 | @Override 573 | public void onError(Throwable e) { 574 | printLog("onError in Subscriber"); 575 | mProgressOperationTwoRunning.setVisibility(View.INVISIBLE); 576 | } 577 | 578 | @Override 579 | public void onNext(String s) { 580 | printLog("onNext " + s + " in Subscriber"); 581 | 582 | } 583 | }); 584 | mCompositeSubscription.add(twoMapSubscription); 585 | } 586 | 587 | private void dosomethingBlockThread() { 588 | printLog("blocking...."); 589 | try { 590 | Thread.sleep(2000); 591 | } catch (InterruptedException e) { 592 | e.printStackTrace(); 593 | } 594 | } 595 | 596 | 597 | private void printLog(String s) { 598 | Log.i(TAG, s + getThreadMessage()); 599 | } 600 | 601 | private String getThreadMessage() { 602 | if (Looper.myLooper() == Looper.getMainLooper()) 603 | return " MainThread"; 604 | else return " Not-MainThread"; 605 | } 606 | 607 | @Override 608 | public void onDestroy() { 609 | super.onDestroy(); 610 | mCompositeSubscription.unsubscribe(); 611 | } 612 | 613 | 614 | } 615 | 616 | 617 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/common/activities/SampleActivityBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.demo.maat.hello_rxjava.common.activities; 18 | 19 | import android.os.Bundle; 20 | import android.support.v4.app.FragmentActivity; 21 | 22 | import com.demo.maat.hello_rxjava.common.logger.Log; 23 | import com.demo.maat.hello_rxjava.common.logger.LogWrapper; 24 | 25 | 26 | /** 27 | * Base launcher activity, to handle most of the common plumbing for samples. 28 | */ 29 | public class SampleActivityBase extends FragmentActivity { 30 | 31 | public static final String TAG = "SampleActivityBase"; 32 | 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | } 37 | 38 | @Override 39 | protected void onStart() { 40 | super.onStart(); 41 | initializeLogging(); 42 | } 43 | 44 | /** Set up targets to receive log data */ 45 | public void initializeLogging() { 46 | // Using Log, front-end to the logging chain, emulates android.util.log method signatures. 47 | // Wraps Android's native log framework 48 | LogWrapper logWrapper = new LogWrapper(); 49 | Log.setLogNode(logWrapper); 50 | 51 | Log.i(TAG, "Ready"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/common/logger/Log.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.demo.maat.hello_rxjava.common.logger; 17 | 18 | /** 19 | * Helper class for a list (or tree) of LoggerNodes. 20 | * 21 | *

When this is set as the head of the list, 22 | * an instance of it can function as a drop-in replacement for {@link android.util.Log}. 23 | * Most of the methods in this class server only to map a method call in Log to its equivalent 24 | * in LogNode.

25 | */ 26 | public class Log { 27 | // Grabbing the native values from Android's native logging facilities, 28 | // to make for easy migration and interop. 29 | public static final int NONE = -1; 30 | public static final int VERBOSE = android.util.Log.VERBOSE; 31 | public static final int DEBUG = android.util.Log.DEBUG; 32 | public static final int INFO = android.util.Log.INFO; 33 | public static final int WARN = android.util.Log.WARN; 34 | public static final int ERROR = android.util.Log.ERROR; 35 | public static final int ASSERT = android.util.Log.ASSERT; 36 | 37 | // Stores the beginning of the LogNode topology. 38 | private static LogNode mLogNode; 39 | 40 | /** 41 | * Returns the next LogNode in the linked list. 42 | */ 43 | public static LogNode getLogNode() { 44 | return mLogNode; 45 | } 46 | 47 | /** 48 | * Sets the LogNode data will be sent to. 49 | */ 50 | public static void setLogNode(LogNode node) { 51 | mLogNode = node; 52 | } 53 | 54 | /** 55 | * Instructs the LogNode to print the log data provided. Other LogNodes can 56 | * be chained to the end of the LogNode as desired. 57 | * 58 | * @param priority Log level of the data being logged. Verbose, Error, etc. 59 | * @param tag Tag for for the log data. Can be used to organize log statements. 60 | * @param msg The actual message to be logged. 61 | * @param tr If an exception was thrown, this can be sent along for the logging facilities 62 | * to extract and print useful information. 63 | */ 64 | public static void println(int priority, String tag, String msg, Throwable tr) { 65 | if (mLogNode != null) { 66 | mLogNode.println(priority, tag, msg, tr); 67 | } 68 | } 69 | 70 | /** 71 | * Instructs the LogNode to print the log data provided. Other LogNodes can 72 | * be chained to the end of the LogNode as desired. 73 | * 74 | * @param priority Log level of the data being logged. Verbose, Error, etc. 75 | * @param tag Tag for for the log data. Can be used to organize log statements. 76 | * @param msg The actual message to be logged. The actual message to be logged. 77 | */ 78 | public static void println(int priority, String tag, String msg) { 79 | println(priority, tag, msg, null); 80 | } 81 | 82 | /** 83 | * Prints a message at VERBOSE priority. 84 | * 85 | * @param tag Tag for for the log data. Can be used to organize log statements. 86 | * @param msg The actual message to be logged. 87 | * @param tr If an exception was thrown, this can be sent along for the logging facilities 88 | * to extract and print useful information. 89 | */ 90 | public static void v(String tag, String msg, Throwable tr) { 91 | println(VERBOSE, tag, msg, tr); 92 | } 93 | 94 | /** 95 | * Prints a message at VERBOSE priority. 96 | * 97 | * @param tag Tag for for the log data. Can be used to organize log statements. 98 | * @param msg The actual message to be logged. 99 | */ 100 | public static void v(String tag, String msg) { 101 | v(tag, msg, null); 102 | } 103 | 104 | 105 | /** 106 | * Prints a message at DEBUG priority. 107 | * 108 | * @param tag Tag for for the log data. Can be used to organize log statements. 109 | * @param msg The actual message to be logged. 110 | * @param tr If an exception was thrown, this can be sent along for the logging facilities 111 | * to extract and print useful information. 112 | */ 113 | public static void d(String tag, String msg, Throwable tr) { 114 | println(DEBUG, tag, msg, tr); 115 | } 116 | 117 | /** 118 | * Prints a message at DEBUG priority. 119 | * 120 | * @param tag Tag for for the log data. Can be used to organize log statements. 121 | * @param msg The actual message to be logged. 122 | */ 123 | public static void d(String tag, String msg) { 124 | d(tag, msg, null); 125 | } 126 | 127 | /** 128 | * Prints a message at INFO priority. 129 | * 130 | * @param tag Tag for for the log data. Can be used to organize log statements. 131 | * @param msg The actual message to be logged. 132 | * @param tr If an exception was thrown, this can be sent along for the logging facilities 133 | * to extract and print useful information. 134 | */ 135 | public static void i(String tag, String msg, Throwable tr) { 136 | println(INFO, tag, msg, tr); 137 | } 138 | 139 | /** 140 | * Prints a message at INFO priority. 141 | * 142 | * @param tag Tag for for the log data. Can be used to organize log statements. 143 | * @param msg The actual message to be logged. 144 | */ 145 | public static void i(String tag, String msg) { 146 | i(tag, msg, null); 147 | } 148 | 149 | /** 150 | * Prints a message at WARN priority. 151 | * 152 | * @param tag Tag for for the log data. Can be used to organize log statements. 153 | * @param msg The actual message to be logged. 154 | * @param tr If an exception was thrown, this can be sent along for the logging facilities 155 | * to extract and print useful information. 156 | */ 157 | public static void w(String tag, String msg, Throwable tr) { 158 | println(WARN, tag, msg, tr); 159 | } 160 | 161 | /** 162 | * Prints a message at WARN priority. 163 | * 164 | * @param tag Tag for for the log data. Can be used to organize log statements. 165 | * @param msg The actual message to be logged. 166 | */ 167 | public static void w(String tag, String msg) { 168 | w(tag, msg, null); 169 | } 170 | 171 | /** 172 | * Prints a message at WARN priority. 173 | * 174 | * @param tag Tag for for the log data. Can be used to organize log statements. 175 | * @param tr If an exception was thrown, this can be sent along for the logging facilities 176 | * to extract and print useful information. 177 | */ 178 | public static void w(String tag, Throwable tr) { 179 | w(tag, null, tr); 180 | } 181 | 182 | /** 183 | * Prints a message at ERROR priority. 184 | * 185 | * @param tag Tag for for the log data. Can be used to organize log statements. 186 | * @param msg The actual message to be logged. 187 | * @param tr If an exception was thrown, this can be sent along for the logging facilities 188 | * to extract and print useful information. 189 | */ 190 | public static void e(String tag, String msg, Throwable tr) { 191 | println(ERROR, tag, msg, tr); 192 | } 193 | 194 | /** 195 | * Prints a message at ERROR priority. 196 | * 197 | * @param tag Tag for for the log data. Can be used to organize log statements. 198 | * @param msg The actual message to be logged. 199 | */ 200 | public static void e(String tag, String msg) { 201 | e(tag, msg, null); 202 | } 203 | 204 | /** 205 | * Prints a message at ASSERT priority. 206 | * 207 | * @param tag Tag for for the log data. Can be used to organize log statements. 208 | * @param msg The actual message to be logged. 209 | * @param tr If an exception was thrown, this can be sent along for the logging facilities 210 | * to extract and print useful information. 211 | */ 212 | public static void wtf(String tag, String msg, Throwable tr) { 213 | println(ASSERT, tag, msg, tr); 214 | } 215 | 216 | /** 217 | * Prints a message at ASSERT priority. 218 | * 219 | * @param tag Tag for for the log data. Can be used to organize log statements. 220 | * @param msg The actual message to be logged. 221 | */ 222 | public static void wtf(String tag, String msg) { 223 | wtf(tag, msg, null); 224 | } 225 | 226 | /** 227 | * Prints a message at ASSERT priority. 228 | * 229 | * @param tag Tag for for the log data. Can be used to organize log statements. 230 | * @param tr If an exception was thrown, this can be sent along for the logging facilities 231 | * to extract and print useful information. 232 | */ 233 | public static void wtf(String tag, Throwable tr) { 234 | wtf(tag, null, tr); 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/common/logger/LogFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | /* 17 | * Copyright 2013 The Android Open Source Project 18 | * 19 | * Licensed under the Apache License, Version 2.0 (the "License"); 20 | * you may not use this file except in compliance with the License. 21 | * You may obtain a copy of the License at 22 | * 23 | * http://www.apache.org/licenses/LICENSE-2.0 24 | * 25 | * Unless required by applicable law or agreed to in writing, software 26 | * distributed under the License is distributed on an "AS IS" BASIS, 27 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 28 | * See the License for the specific language governing permissions and 29 | * limitations under the License. 30 | */ 31 | 32 | package com.demo.maat.hello_rxjava.common.logger; 33 | 34 | import android.graphics.Typeface; 35 | import android.os.Bundle; 36 | import android.support.v4.app.Fragment; 37 | import android.text.Editable; 38 | import android.text.TextWatcher; 39 | import android.view.Gravity; 40 | import android.view.LayoutInflater; 41 | import android.view.View; 42 | import android.view.ViewGroup; 43 | import android.widget.ScrollView; 44 | 45 | /** 46 | * Simple fraggment which contains a LogView and uses is to output log data it receives 47 | * through the LogNode interface. 48 | */ 49 | public class LogFragment extends Fragment { 50 | 51 | private LogView mLogView; 52 | private ScrollView mScrollView; 53 | 54 | public LogFragment() {} 55 | 56 | public View inflateViews() { 57 | mScrollView = new ScrollView(getActivity()); 58 | ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams( 59 | ViewGroup.LayoutParams.MATCH_PARENT, 60 | ViewGroup.LayoutParams.MATCH_PARENT); 61 | mScrollView.setLayoutParams(scrollParams); 62 | 63 | mLogView = new LogView(getActivity()); 64 | ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams); 65 | logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; 66 | mLogView.setLayoutParams(logParams); 67 | mLogView.setTextSize(10); 68 | mLogView.setClickable(true); 69 | mLogView.setFocusable(true); 70 | mLogView.setTypeface(Typeface.MONOSPACE); 71 | 72 | // Want to set padding as 16 dips, setPadding takes pixels. Hooray math! 73 | int paddingDips = 16; 74 | double scale = getResources().getDisplayMetrics().density; 75 | int paddingPixels = (int) ((paddingDips * (scale)) + .5); 76 | mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels); 77 | mLogView.setCompoundDrawablePadding(paddingPixels); 78 | 79 | mLogView.setGravity(Gravity.BOTTOM); 80 | mLogView.setTextAppearance(getActivity(), android.R.style.TextAppearance_Holo_Medium); 81 | 82 | mScrollView.addView(mLogView); 83 | return mScrollView; 84 | } 85 | 86 | @Override 87 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 88 | Bundle savedInstanceState) { 89 | 90 | View result = inflateViews(); 91 | 92 | mLogView.addTextChangedListener(new TextWatcher() { 93 | @Override 94 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {} 95 | 96 | @Override 97 | public void onTextChanged(CharSequence s, int start, int before, int count) {} 98 | 99 | @Override 100 | public void afterTextChanged(Editable s) { 101 | //afterTextChanged 在 text发生改变后马上被调用,此时可能text还未被绘制,导致无法滑动到最底部 102 | //所以不能直接调用,而应该使用post 103 | mScrollView.post(new Runnable(){ 104 | @Override 105 | public void run() { 106 | mScrollView.fullScroll(ScrollView.FOCUS_DOWN); 107 | } 108 | }); 109 | } 110 | }); 111 | return result; 112 | } 113 | 114 | public LogView getLogView() { 115 | return mLogView; 116 | } 117 | } -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/common/logger/LogNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.demo.maat.hello_rxjava.common.logger; 17 | 18 | /** 19 | * Basic interface for a logging system that can output to one or more targets. 20 | * Note that in addition to classes that will output these logs in some format, 21 | * one can also implement this interface over a filter and insert that in the chain, 22 | * such that no targets further down see certain data, or see manipulated forms of the data. 23 | * You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data 24 | * it received to HTML and sent it along to the next node in the chain, without printing it 25 | * anywhere. 26 | */ 27 | public interface LogNode { 28 | 29 | /** 30 | * Instructs first LogNode in the list to print the log data provided. 31 | * @param priority Log level of the data being logged. Verbose, Error, etc. 32 | * @param tag Tag for for the log data. Can be used to organize log statements. 33 | * @param msg The actual message to be logged. The actual message to be logged. 34 | * @param tr If an exception was thrown, this can be sent along for the logging facilities 35 | * to extract and print useful information. 36 | */ 37 | public void println(int priority, String tag, String msg, Throwable tr); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/common/logger/LogView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.demo.maat.hello_rxjava.common.logger; 17 | 18 | import android.app.Activity; 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.widget.TextView; 22 | 23 | /** Simple TextView which is used to output log data received through the LogNode interface. 24 | */ 25 | public class LogView extends TextView implements LogNode { 26 | 27 | public LogView(Context context) { 28 | super(context); 29 | } 30 | 31 | public LogView(Context context, AttributeSet attrs) { 32 | super(context, attrs); 33 | } 34 | 35 | public LogView(Context context, AttributeSet attrs, int defStyle) { 36 | super(context, attrs, defStyle); 37 | } 38 | 39 | /** 40 | * Formats the log data and prints it out to the LogView. 41 | * @param priority Log level of the data being logged. Verbose, Error, etc. 42 | * @param tag Tag for for the log data. Can be used to organize log statements. 43 | * @param msg The actual message to be logged. The actual message to be logged. 44 | * @param tr If an exception was thrown, this can be sent along for the logging facilities 45 | * to extract and print useful information. 46 | */ 47 | @Override 48 | public void println(int priority, String tag, String msg, Throwable tr) { 49 | 50 | 51 | String priorityStr = null; 52 | 53 | // For the purposes of this View, we want to print the priority as readable text. 54 | switch(priority) { 55 | case android.util.Log.VERBOSE: 56 | priorityStr = "VERBOSE"; 57 | break; 58 | case android.util.Log.DEBUG: 59 | priorityStr = "DEBUG"; 60 | break; 61 | case android.util.Log.INFO: 62 | priorityStr = "INFO"; 63 | break; 64 | case android.util.Log.WARN: 65 | priorityStr = "WARN"; 66 | break; 67 | case android.util.Log.ERROR: 68 | priorityStr = "ERROR"; 69 | break; 70 | case android.util.Log.ASSERT: 71 | priorityStr = "ASSERT"; 72 | break; 73 | default: 74 | break; 75 | } 76 | 77 | // Handily, the Log class has a facility for converting a stack trace into a usable string. 78 | String exceptionStr = null; 79 | if (tr != null) { 80 | exceptionStr = android.util.Log.getStackTraceString(tr); 81 | } 82 | 83 | // Take the priority, tag, message, and exception, and concatenate as necessary 84 | // into one usable line of text. 85 | final StringBuilder outputBuilder = new StringBuilder(); 86 | 87 | String delimiter = "\t"; 88 | appendIfNotNull(outputBuilder, priorityStr, delimiter); 89 | appendIfNotNull(outputBuilder, tag, delimiter); 90 | appendIfNotNull(outputBuilder, msg, delimiter); 91 | appendIfNotNull(outputBuilder, exceptionStr, delimiter); 92 | 93 | // In case this was originally called from an AsyncTask or some other off-UI thread, 94 | // make sure the update occurs within the UI thread. 95 | ((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() { 96 | @Override 97 | public void run() { 98 | // Display the text we just generated within the LogView. 99 | appendToLog(outputBuilder.toString()); 100 | } 101 | }))); 102 | 103 | if (mNext != null) { 104 | mNext.println(priority, tag, msg, tr); 105 | } 106 | } 107 | 108 | public LogNode getNext() { 109 | return mNext; 110 | } 111 | 112 | public void setNext(LogNode node) { 113 | mNext = node; 114 | } 115 | 116 | /** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since 117 | * the logger takes so many arguments that might be null, this method helps cut out some of the 118 | * agonizing tedium of writing the same 3 lines over and over. 119 | * @param source StringBuilder containing the text to append to. 120 | * @param addStr The String to append 121 | * @param delimiter The String to separate the source and appended strings. A tab or comma, 122 | * for instance. 123 | * @return The fully concatenated String as a StringBuilder 124 | */ 125 | private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) { 126 | if (addStr != null) { 127 | if (addStr.length() == 0) { 128 | delimiter = ""; 129 | } 130 | 131 | return source.append(addStr).append(delimiter); 132 | } 133 | return source; 134 | } 135 | 136 | // The next LogNode in the chain. 137 | LogNode mNext; 138 | 139 | /** Outputs the string as a new line of log data in the LogView. */ 140 | public void appendToLog(String s) { 141 | append("\n" + s); 142 | } 143 | 144 | 145 | } 146 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/common/logger/LogWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.demo.maat.hello_rxjava.common.logger; 17 | 18 | import android.util.Log; 19 | 20 | /** 21 | * Helper class which wraps Android's native Log utility in the Logger interface. This way 22 | * normal DDMS output can be one of the many targets receiving and outputting logs simultaneously. 23 | */ 24 | public class LogWrapper implements LogNode { 25 | 26 | // For piping: The next node to receive Log data after this one has done its work. 27 | private LogNode mNext; 28 | 29 | /** 30 | * Returns the next LogNode in the linked list. 31 | */ 32 | public LogNode getNext() { 33 | return mNext; 34 | } 35 | 36 | /** 37 | * Sets the LogNode data will be sent to.. 38 | */ 39 | public void setNext(LogNode node) { 40 | mNext = node; 41 | } 42 | 43 | /** 44 | * Prints data out to the console using Android's native log mechanism. 45 | * @param priority Log level of the data being logged. Verbose, Error, etc. 46 | * @param tag Tag for for the log data. Can be used to organize log statements. 47 | * @param msg The actual message to be logged. The actual message to be logged. 48 | * @param tr If an exception was thrown, this can be sent along for the logging facilities 49 | * to extract and print useful information. 50 | */ 51 | @Override 52 | public void println(int priority, String tag, String msg, Throwable tr) { 53 | // There actually are log methods that don't take a msg parameter. For now, 54 | // if that's the case, just convert null to the empty string and move on. 55 | String useMsg = msg; 56 | if (useMsg == null) { 57 | useMsg = ""; 58 | } 59 | 60 | // If an exeption was provided, convert that exception to a usable string and attach 61 | // it to the end of the msg method. 62 | if (tr != null) { 63 | msg += "\n" + Log.getStackTraceString(tr); 64 | } 65 | 66 | // This is functionally identical to Log.x(tag, useMsg); 67 | // For instance, if priority were Log.VERBOSE, this would be the same as Log.v(tag, useMsg) 68 | Log.println(priority, tag, useMsg); 69 | 70 | // If this isn't the last node in the chain, move things along. 71 | if (mNext != null) { 72 | mNext.println(priority, tag, msg, tr); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/common/logger/MessageOnlyLogFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.demo.maat.hello_rxjava.common.logger; 17 | 18 | /** 19 | * Simple {@link LogNode} filter, removes everything except the message. 20 | * Useful for situations like on-screen log output where you don't want a lot of metadata displayed, 21 | * just easy-to-read message updates as they're happening. 22 | */ 23 | public class MessageOnlyLogFilter implements LogNode { 24 | 25 | LogNode mNext; 26 | 27 | /** 28 | * Takes the "next" LogNode as a parameter, to simplify chaining. 29 | * 30 | * @param next The next LogNode in the pipeline. 31 | */ 32 | public MessageOnlyLogFilter(LogNode next) { 33 | mNext = next; 34 | } 35 | 36 | public MessageOnlyLogFilter() { 37 | } 38 | 39 | @Override 40 | public void println(int priority, String tag, String msg, Throwable tr) { 41 | if (mNext != null) { 42 | getNext().println(Log.NONE, null, msg, null); 43 | } 44 | } 45 | 46 | /** 47 | * Returns the next LogNode in the chain. 48 | */ 49 | public LogNode getNext() { 50 | return mNext; 51 | } 52 | 53 | /** 54 | * Sets the LogNode data will be sent to.. 55 | */ 56 | public void setNext(LogNode node) { 57 | mNext = node; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/retrofit/ZhihuApi.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava.retrofit; 2 | 3 | 4 | import com.demo.maat.hello_rxjava.retrofit.zhihu.ZhihuDaily; 5 | 6 | import retrofit2.http.GET; 7 | import rx.Observable; 8 | 9 | 10 | public interface ZhihuApi { 11 | 12 | @GET("/api/4/news/latest") 13 | Observable getLastDaily(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/retrofit/zhihu/ZhihuDaily.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava.retrofit.zhihu; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * Created by 蔡小木 on 2016/3/6 0006. 9 | */ 10 | public class ZhihuDaily{ 11 | @SerializedName("date") 12 | private String date; 13 | @SerializedName("top_stories") 14 | private ArrayList mZhihuDailyItems; 15 | @SerializedName("stories") 16 | private ArrayList stories; 17 | 18 | public String getDate() { 19 | return date; 20 | } 21 | 22 | public void setDate(String date) { 23 | this.date = date; 24 | } 25 | 26 | public ArrayList getZhihuDailyItems() { 27 | return mZhihuDailyItems; 28 | } 29 | 30 | public void setZhihuDailyItems(ArrayList zhihuDailyItems) { 31 | this.mZhihuDailyItems = zhihuDailyItems; 32 | } 33 | 34 | public ArrayList getStories() { 35 | return stories; 36 | } 37 | 38 | public void setStories(ArrayList stories) { 39 | this.stories = stories; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/retrofit/zhihu/ZhihuDailyItem.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava.retrofit.zhihu; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Created by 蔡小木 on 2016/3/6 0006. 7 | */ 8 | public class ZhihuDailyItem{ 9 | @SerializedName("images") 10 | private String[] images; 11 | @SerializedName("type") 12 | private int type; 13 | @SerializedName("id") 14 | private String id; 15 | @SerializedName("title") 16 | private String title; 17 | private String date; 18 | public boolean hasFadedIn = false; 19 | 20 | public String[] getImages() { 21 | return images; 22 | } 23 | 24 | public void setImages(String[] images) { 25 | this.images = images; 26 | } 27 | 28 | public int getType() { 29 | return type; 30 | } 31 | 32 | public void setType(int type) { 33 | this.type = type; 34 | } 35 | 36 | public String getId() { 37 | return id; 38 | } 39 | 40 | public void setId(String id) { 41 | this.id = id; 42 | } 43 | 44 | public String getTitle() { 45 | return title; 46 | } 47 | 48 | public void setTitle(String title) { 49 | this.title = title; 50 | } 51 | 52 | public String getDate() { 53 | return date; 54 | } 55 | 56 | public void setDate(String date) { 57 | this.date = date; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/demo/maat/hello_rxjava/retrofit/zhihu/ZhihuManager.java: -------------------------------------------------------------------------------- 1 | package com.demo.maat.hello_rxjava.retrofit.zhihu; 2 | 3 | import com.demo.maat.hello_rxjava.retrofit.ZhihuApi; 4 | 5 | import retrofit2.Retrofit; 6 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; 7 | import retrofit2.converter.gson.GsonConverterFactory; 8 | 9 | /** 10 | * Created by xinghongfei on 16/10/5. 11 | */ 12 | 13 | public class ZhihuManager { 14 | private static ZhihuManager mManager; 15 | 16 | public ZhihuApi zhihuApi; 17 | public static ZhihuManager getInstance(){ 18 | 19 | if (mManager==null){ 20 | mManager= new ZhihuManager(); 21 | } 22 | return mManager; 23 | } 24 | 25 | public ZhihuApi getZhihuApiService() { 26 | if (zhihuApi == null) { 27 | if (zhihuApi == null) { 28 | zhihuApi = new Retrofit.Builder() 29 | .baseUrl("http://news-at.zhihu.com") 30 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 31 | .addConverterFactory(GsonConverterFactory.create()) 32 | .build().create(ZhihuApi.class); 33 | 34 | } 35 | } 36 | 37 | return zhihuApi; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tile.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xinghongfei/Hello-RxJava/5969c976b5eeba764bc65cbc7d946c7a2f596210/app/src/main/res/drawable/tile.9.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 23 | 24 |