如何解决android observer模式出现onerror时的程序闪退问题

安卓 6.0获取位置权限造成闪退 - 简书
<div class="fixed-btn note-fixed-download" data-toggle="popover" data-placement="left" data-html="true" data-trigger="hover" data-content=''>
写了141227字,被125人关注,获得了194个喜欢
安卓 6.0获取位置权限造成闪退
安卓 6.0获取位置权限造成闪退 开发用下面的方法解决的。1.简介RxPermissions是基于RxJava开发的用于帮助在Android 6.0中处理运行时权限检测的框架。在Android 6.0中,系统新增了部分权限的运行时动态获取。而不再是在以前的版本中安装的时候授予权限。
对于运行时的权限获取提示,国内的Android工程师们应该并不陌生,国内的第三方ROM例如MIUI在很早前就做了类似的功能。但是第三方ROM并不能提供给我们权限请求成功或失败的接口,这就导致我们无法通过PackageManager提供的checkPermission()方法来准确的获取到我们是否获得该权限。只能根据具体的权限来做相应的处理。但是在Android 6.0中我们可以准确的获取我们的应用是否获取某个权限,具体的方法希望大家看这篇文章:Android 6.0 运行时权限处理。大致方法是通过API 23中的Activity的requestPermissions(String[] permissions, int requestCode);方法请求权限,并在onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults)回调方法中处理请求结果。这个方法与onActivityResult()类似。RxPermissions在这个基础上做了封装,使我们在处理运行时权限变得更加的简单。
另外关于RxJava如果你现在还没了解过RxJava可以直接翻到文章最下面去查看我总结的一些RxJava相关的文章,不然并不推荐直接看这篇文章。下面我们就来具体看看RxPermissions的使用方法以及源码分析。
2.使用方法1.直接获取权限(使用Retrolambda使代码更加简洁,当然并不是必须使用):
// 必须在初始化阶段调用,例如onCreate()方法中
RxPermissions.getInstance(this)
.request(Manifest.permission.CAMERA)
.subscribe(granted -& {
if (granted) { // 在android 6.0之前会默认返回true
// 已经获取权限
// 未获取权限
2.通过条件触发获取权限(结合RxBinding使用)
// 必须在初始化阶段调用,例如onCreate()方法中
RxView.clicks(findViewById(R.id.enableCamera))
.compose(RxPermissions.getInstance(this).ensure(Manifest.permission.CAMERA))
.subscribe(granted -& {
// 当R.id.enableCamera被点击的时候触发获取权限
3.一次请求多个权限(有两种方式)
如果同时请求多个权限,下面这种方式会合并请求结果,即所有权限请求成功会返回true,若有一个权限未成功则返回false。
RxPermissions.getInstance(this)
.request(Manifest.permission.CAMERA,
Manifest.permission.READ_PHONE_STATE)
.subscribe(granted -& {
if (granted) {
// 所有权限请求被同意
// 至少有一个权限没同意
当然你可以通过requestEach or ensureEach 来分别获取每一个权限请求的结果。
RxPermissions.getInstance(this)
.requestEach(Manifest.permission.CAMERA,
Manifest.permission.READ_PHONE_STATE)
.subscribe(permission -& { // 会发送两个Permission对象
if (permission.granted) {
// `permission.name` is granted !
注意:由于在请求权限的过程中app有可能会被重启,所以权限请求必须放在初始化的阶段,比如在Activity.onCreate/onResume, 或者View.onFinishInflate方法中。如果不这样处理,那么如果app在请求过程中重启的话,权限请求结果将不会发送给订阅者即subscriber。
2.整体介绍RxPermission一共就只有三个类:Permission是定义的权限model类,用来存放权限名称以及是否获取权限的信息。RxPermissions就是最主要的类了,利用RxJava提供了我们上面在使用方法中介绍的所有方法。还有一个ShadowActivity类是用来请求权限用的。下面我们就来详细介绍RxPermission的实现。
注意:如果你还未了解过RxJava那么可以先阅读本文最后的一系列优秀文章。如果你已经了解过RxJava的话,那么下面我将会介绍RxJava中的部分操作符在RxPermission中的实际运用。相信能帮助你更好的理解RxJava中操作符的使用。
3.源码分析我们依然按照我们惯用的方法来分析,通过使用方法来分析调用流程,最终理解整个项目。首先再回顾一遍使用方法(注意这里我同时请求了两个权限),那么结果将是如果所有权限请求成功会返回true,若有一个权限未成功则返回false。代码如下:
// 必须在初始化阶段调用,例如onCreate()方法中
RxPermissions.getInstance(this)
.request(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
.subscribe(granted -& {
if (granted) { // 在android 6.0之前会默认返回true
// 已经获取权限
// 未获取权限
1.RxPermissions.getInstance(this)的实现
static RxPermissions sS
private Context :;
public static RxPermissions getInstance(Context) {
if (sSingleton == null) {
sSingleton = new RxPermissions(ctx.getApplicationContext());
RxPermissions(Context ctx) {
很明显是维护RxPermissions的单例,不再多做介绍,紧接着我们来看RxPermissions中request(Manifest.permission.CAMERA)方法的实现:
2.request(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)的实现:
public Observable&Boolean& request(final String... permissions) {
return Observable.just(null).compose(ensure(permissions));
首先从返回值看到是返回一个Observable&Boolean&对象,方法中也是直接return了Observable.just(null).compose(ensure(permissions))。这里涉及两个方法分别是just()以及compose()我们先解释这两个操作符:
1.Observable.just(null)
just操作符可以将某个对象转化为Observable对象,并且将其发射出去,可以是一个数字、一个字符串、数组、Iterate对象等,是RxJava中非常快捷的创建Observable对象的方法。在这里just()方法中虽然传入的是null但是并不影响创建出的Observable的作用,如果有subscriber订阅依然会依次调用其onNext()和onCompleted()方法。所以这里就是为了创建出一个Observable对象,便于后续的处理。创建完Observable对象之后紧接着调用了compose()方法:
<pose(Transformer)操作符
compose()操作符是针对Observable自身的变换,通过我们自己定义的Transformer对象可以将对Observable对象变换的操作封装起来,实现一个简单的Transformer对象如下:
class myTransformer implements Observable.Transformer&Object, Boolean& {
public Observable&Boolean& call(Observable&Object& objectObservable) {
return objectObservable.map(new Func1&Object, Boolean&() {
public Boolean call(Object o) {
通过上面这个Transformer就可以将任何Observable&Object&对象转换成Observable&Boolean&对象了。当然在Transformer里你也可以返回一个全新的Observable对象。RxPermissions就是这样做的,那么回到项目中再来看compose(ensure(permissions));那么ensure(permissions);一定是返回一个Transformer对象了。
3.ensure(permissions);方法的实现
我们来看看ensure(permissions)方法的实现:
public Observable.Transformer&Object, Boolean& ensure(final String... permissions) {
//创建一个Transformer对象返回
return new Observable.Transformer&Object, Boolean&() {
// o表示当前Observable对象。
public Observable&Boolean& call(Observable&Object& o) {
//request(o, permissions) 方法返回 Observable&Permission&对象
return request(o, permissions)
// 将Observable&Permission&转换为Observable&Boolean&
// buffer操作符
.buffer(permissions.length)
// flatMap操作符
.flatMap(new Func1&List&Permission&, Observable&Boolean&&() {
public Observable&Boolean& call(List&Permission& permissions) {
// 如果permissions为空那么直接返回Observable.empty();
if (permissions.isEmpty()) {
// Occurs during orientation change, when the subject receives onComplete.
// In that case we don't want to propagate that empty list to the
// subscriber, only the onComplete.
return Observable.empty();
// 遍历所有Permission,如果有一个未成功则返回false,全部成功返回true。
for (Permission p : permissions) {
if (!p.granted) {
return Observable.just(false);
return Observable.just(true);
确实是返回一个Observable.Transformer对象,那么在call()方法里首先调用了request(o, permissions)方法,然后又进行了buffer()和flatMap()的处理,最终会返回Observable.empty();、Observable.just(false);或Observable.just(true);对象。我们先来看看request(o, permissions)方法的实现:
4.request(o, permissions);方法的实现
private Observable&Permission& request(final Observable&?& trigger,
final String... permissions) {
//如果并没有请求的权限则抛出异常
if (permissions == null || permissions.length == 0) {
throw new IllegalArgumentException("RxPermissions.request/requestEach requires at least one input permission");
return oneOf(trigger, pending(permissions))
.flatMap(new Func1&Object, Observable&Permission&&() {
public Observable&Permission& call(Object o) {
return request_(permissions);
首先对permissions做了判断,然后调用了oneOf(trigger, pending(permissions))方法,并通过flatMap()操作符在call()方法中调用了request_(permissions);按照惯例我们应该去看oneOf()方法的实现了。但是oneOf()方法里其实并没有什么实际意义,看了项目的commit log我觉得应该是历史遗留问题,作者可能是想处理一些相同重复的权限请求,但是并没有实现。所以其实这个方法完全可以这样代替;
private Observable&Permission& request(final Observable&?& trigger,
final String... permissions) {
return request_(permissions);
直接调用request_(permissions);即可。我测试中并没有发现问题。目前我还没有联系到作者询问这个方法的实现目的,稍后可能会提一个issue,如果有结果会在文章中更新。所以这里大家就完全可以理解成直接调用了request_(permissions);方法:
5.request_(permissions);方法的实现
@TargetApi(Build.VERSION_CODES.M)
private Observable&Permission& request_(final String... permissions) {
//创建出一个存放Observable&Permission&的list
List&Observable&Permission&& list = new ArrayList&&(permissions.length);
//存放还为请求权限的list
List&String& unrequestedPermissions = new ArrayList&&();
// 在请求多个权限的时候,我们为每一个请求的权限都创建一个observable对象,在最后
// 这些observable会被合并成一个response。
for (String permission : permissions) {
log("Requesting permission " + permission);
//如果是已经获得的权限,或者Android版本在6.0之前则直接添加一个
// Observable.just(new Permission(permission, true))对象.
if (isGranted(permission)) {
// Already granted, or not Android M
// Return a granted Permission object.
list.add(Observable.just(new Permission(permission, true)));
// 如果是已经拒绝的权限则添加
// Observable.just(new Permission(permission, false))对象.
if (isRevoked(permission)) {
// Revoked by a policy, return a denied Permission object.
list.add(Observable.just(new Permission(permission, false)));
PublishSubject&Permission& subject = mSubjects.get(permission);
// 如果mSubjects 不存在当前 permission,则添加到unrequestedPermissions中
// 并且创建PublishSubject对象并添加到mSubjects中。
if (subject == null) {
unrequestedPermissions.add(permission);
subject = PublishSubject.create();
mSubjects.put(permission, subject);
//并且添加到list中
list.add(subject);
//如果有未请求的权限
if (!unrequestedPermissions.isEmpty()) {
startShadowActivity(unrequestedPermissions
.toArray(new String[unrequestedPermissions.size()]));
return Observable.concat(Observable.from(list));
void startShadowActivity(String[] permissions) {
log("startShadowActivity " + TextUtils.join(", ", permissions));
Intent intent = new Intent(mCtx, ShadowActivity.class);
intent.putExtra("permissions", permissions);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mCtx.startActivity(intent);
代码如上,注释非常清晰,整体上就是将已经允许的权限和已经拒绝过的权限添加到list中,并且将还未请求的权限分别添加到mSubjects与list中。然后调用startShadowActivity();方法。最后通过Observable.concat(Observable.from(list));返回。这里主要包含PublishSubject与concat()操作符的知识:
6.PublishSubject对象
从PublishSubject的文档中,可以看出是继承自Subject,Subject是既可以充当Observer又能充当Observable的。从文档中的Example中可以看到订阅PublishSubject的observer只会接收到订阅之后PublishSubject发送的数据,但是本项目中并没有体现出此特性,主要是利用PublishSubject中的onNext()和onCompleted()方法,这里大致了解这么多,下面是Example的代码:
PublishSubject&Object& subject = PublishSubject.create();
// observer1 will receive all onNext and onCompleted events
subject.subscribe(observer1);
subject.onNext("one");
subject.onNext("two");
// observer2 will only receive "three" and onCompleted
subject.subscribe(observer2);
subject.onNext("three");
subject.onCompleted();
7.concat()操作符
Concat操作符将多个Observable结合成一个Observable并发射数据,并且严格按照先后顺序发射数据,前一个Observable的数据没有发射完,是不能发射后面Observable的数据的。引用自此篇文章。所以在本项目中Concat()是为了保证请求的权限按顺序返回。接下来我们看看ShadowActivity的实现:
8.ShadowActivity的实现
@TargetApi(Build.VERSION_CODES.M)
public class ShadowActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
handleIntent(getIntent());
protected void onNewIntent(Intent intent) {
handleIntent(intent);
private void handleIntent(Intent intent) {
String[] permissions = intent.getStringArrayExtra("permissions");
requestPermissions(permissions, 42);
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
RxPermissions.getInstance(this).onRequestPermissionsResult(requestCode, permissions, grantResults);
很简单其实就是按照系统提供给我们的方法进行权限请求,最后回调RxPermissions的onRequestPermissionsResult()方法:
9.onRequestPermissionsResult()方法的实现
void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
for (int i = 0, size = permissions. i & i++) {
log("onRequestPermissionsResult
" + permissions[i]);
// 取出对应的PublishSubject对象
PublishSubject&Permission& subject = mSubjects.get(permissions[i]);
if (subject == null) {
// No subject found
throw new IllegalStateException("RxPermissions.onRequestPermissionsResult invoked but didn't find the corresponding permission request.");
//从mSubjects移除
mSubjects.remove(permissions[i]);
//获取结果
boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
//调用onNext()方法发送结果
subject.onNext(new Permission(permissions[i], granted));
//调用onCompleted()方法。
subject.onCompleted();
简单的来说就是拿到结果并发送结果。所以就又回到了最初的ensure(permissions);方法中的request(o, permissions)之后,代码如下:
request(o, permissions)
// 将Observable&Permission&转换为Observable&Boolean&
// buffer操作符
.buffer(permissions.length)
// flatMap操作符
.flatMap(new Func1&List&Permission&, Observable&Boolean&&() {
public Observable&Boolean& call(List&Permission& permissions) {
// 如果permissions为空那么直接返回Observable.empty();
if (permissions.isEmpty()) {
// Occurs during orientation change, when the subject receives onComplete.
// In that case we don't want to propagate that empty list to the
// subscriber, only the onComplete.
return Observable.empty();
// 遍历所有Permission,如果有一个未成功则返回false,全部成功返回true。
for (Permission p : permissions) {
if (!p.granted) {
return Observable.just(false);
return Observable.just(true);
所以这里会不断的发送Observable&Permission&对象,请求了几个权限就会发送几次,但是这里用了一个buffer()操作符,关于buffer()操作符:
10.buffer()操作符
buffer英文是缓冲区的意思。所以Buffer操作符所要做的事情就是将数据按照规定的大小做一下缓存,然后将缓存的数据作为一个集合发射出去。详细可以看这里,所以在本项目中就是讲这些Observable&Permission&转换成Observable&List&Permission&&对象,紧接着又使用了flatMap()操作符然后返回了我们最终的结果。以上就是整个的调用流程了,如果有不清楚的建议可以多多的调试RxPermission的代码以及查阅各种资料帮助理解。
requestEach()、ensureEach()、ensure()的实现
以上我们分析了request()方法的实现,看似好像还剩下上面三个方法没有分析。其实仔细看的同学应该已经看明白了。上面三个方法其实都是差不多的。如果你看懂了request()方法的实现,那么这三个方法你一定能看懂,有兴趣的同学可以自行去源码里研究。
4.个人评价其实Android 6.0的权限处理我自己在项目中都没有使用过,因为拿目前国内市场来说,首先Android 6.0的手机占有量非常少。再者我们可以使用很简单的方法将targetSdkVersion设置为22来兼容6.0的权限处理。所以目前项目中应该很少需要使用RxPermissions这个项目。但是这个项目作为RxJava的学习资料是相当的好。从中我们可以学到大量的RxJava相关的使用知识。如果你现在在学习RxJava,强烈推荐这个项目。
原文来自:
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
选择支付方式:I am using Retrofit to access my API as follows:
public interface UserService {
@POST("/user/login")
public Observable&User& register(@Body() User user);
Here is how I access my API:
mUserService.register(user)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer&User&() {
public void onCompleted() {
public void onError(Throwable e) {
public void onNext(User user) {
This works perfectly well, except when there is an exception (i.e. IOException, or when connection times out), the onError method doesn't get fired, instead I get an exception on the main thread which terminates my application.
However, for some cases (such as when the API call responds with status code 400), the onError method is fired as expected.
After digging the logcat output, I have spotted this line, (not sure how I am supposed to deal with this)
rx.exceptions.OnErrorFailedException: Error occurred when trying to propagate error to Observer.onError
Can someone let me know where I am doing things wrong?
解决方案 In my previous experience with RxJava the OnErrorFailedException means that an exception occurred while handling another exception in the onError method.
If you don't see stack trace of the real cause it's probably due the bug in RxJava with CompositeException (versions 0.19.2 and above)
As a workaround try to wrap your onError code within try-catch block and log the exception. This way you will see what's the problem with your onError implementation and you will be able to solve the problem.
public void onError(Throwable e) {
catch(Throwable e) {
// Log the exception
本文地址: &
我使用的改造来访问我的API如下:
公共接口UserService的{
@POST(“/用户/登录”)
公众可观察&使用者&GT;注册(@Body()用户用户);
下面是如何访问我的API:
mUserService.register(用户)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(新观察&使用者&GT;(){
公共无效onCompleted(){
公共无效onerror的(可抛出E){
公共无效onNext(用户用户){
这工作得很好,除非有一个例外(即IOException异常,或当连接超时),则onError方法不被解雇,而不是我得到它终止我的应用程序的主线程上的异常。
然而,对于某些情况下(当API调用,状态code 400的响应,如),该onError方法烧制预期。
挖掘的logcat输出后,我发现这条线,(不知道如何我应该处理这个)
rx.exceptions.OnErrorFailedException:试图传播错误Observer.onError时发生错误
有人可以让我知道我在做的事情错了?
解决方案 在我的$ P $与RxJava pvious经验 OnErrorFailedException 表示,虽然处理另一个异常发生异常在的onError 方法。
如果你看不到的真正原因很可能是由于在RxJava错误与 CompositeException (版本0.19.2及以上)堆栈跟踪/Netflix/RxJava/issues/1405
作为一种变通方法尝试包装你的的onError
code在的try-catch 块,并记录异常。这样,你会看到什么是你的的onError 的实施问题,您将能够解决的问题。
公共无效onerror的(可抛出E){
捕获(的Throwable E){
//记录异常
本文地址: &
扫一扫关注官方微信RxAndroid 实践快速入门
一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库。用一个词概括:异步,也就是说RxJava也可以理解为一个处理异步的类库。Android也提供了处理异步的工具AsyncTask、Handler,当我们处理较复杂的异步时
一、Rx概念
RxJava官方定义
一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库。用一个词概括:异步,也就是说RxJava也可以理解为一个处理异步的类库。也提供了处理异步的工具AsyncTask、Handler,当我们处理较复杂的异步时,异步代码难写且难以读懂。RxJava相对于AsyncTask和Handler的好处就是让异步处理代码显得更简洁易懂。
RxJava的异步实现,是通过一种扩展的观察者模式来实现的。
RxJava 的观察者模式
RxJava 有四个基本概念:Observable (可观察者,即被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。Observable 和Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer。与传统观察者模式不同, RxJava 的事件回调方法除了普通事件 onNext()之外,还定义了两个特殊的事件:onCompleted() 和 onError()。
onCompleted(): 事件队列完结。RxJava不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的onNext() 发出时,需要触发 onCompleted() 方法作为标志。
onError(): 事件队列异常。在事件处理过程中出异常时,onError()会被触发,同时队列自动终止,不允许再有事件发出。
二、RxJava实现过程
1) 创建 Observer
Observer 即观察者,它决定事件触发的时候将有怎样的行为。 RxJava 中的 Observer 接口的实现方式:
Observer observer = new Observer() {
public void onCompleted() {
public void onError(Throwable e) {
public void onNext(String s) {
除了 Observer 接口之外,RxJava 还内置了一个实现了 Observer 的抽象类:Subscriber。 Subscriber 对 Observer 接口进行了一些扩展,但他们的基本使用方式是完全一样的:
Subscriber subscriber = new Subscriber() {
public void onCompleted() {
public void onError(Throwable e) {
public void onNext(String s) {
2) 创建 Observable
Observable 即被观察者,它决定什么时候触发事件以及触发怎样的事件。 RxJava 使用create()方法来创建一个 Observable ,并为它定义事件触发规则:
Observable observable = Observable.create(new Observable.OnSubscribe() {
public void call(Subscriber subscriber) {
Observable常见的创建方式还有有如下3种:
fromCallable():方法传入的参数类型是泛型。
Observable observable = Observable.fromCallable(new Callable() {
public String call() throws Exception {
just():方法传入的参数支持List、数组、多参数。
Observable<list& observer = Observable.just(getArrays());</list
from():方法传入的参数支持List、数组、多参数。
Observable observable = Observable.from(getArrays());
3) Subscribe (订阅)
创建了Observable和Observer之后,再用subscribe()方法将它们联结起来,整条链子就可以工作了。
observable.subscribe(observer);
三、RxJava线程控制--Scheduler
在RxJava 中,Scheduler --调度器,相当于线程控制器,RxJava 通过它来指定每一段代码应该运行在什么样的线程。RxJava 已经内置了几个Scheduler,它们已经适合大多数的使用场景:
Schedulers.immediate(): 直接在当前线程运行,相当于不指定线程。这是默认的Scheduler。Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。Schedulers.io(): I/O 操作(读写文件、读写、网络信息交互等)所使用的Scheduler。putation(): 计算所使用的Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。Android 还有一个专用的AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行。
有了这几个Scheduler,就可以使用subscribeOn()和observeOn()两个方法来对线程进行控制了。 subscribeOn(): 指定subscribe()所发生的线程,即Observable.OnSubscribe被激活时所处的线程。或者叫做事件产生的线程。 observeOn(): 指定Subscriber所运行在的线程。或者叫做事件消费的线程。
mSubcription = observerable
//指定subscribe发生在io线程
.subscribeOn(Schedulers.io())
//指定subscribe回调发生在UI线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<list&() {
public void onCompleted() {
public void onError(Throwable e) {
public void onNext(List list) {
displayRecyclerView(list);
四、RxJava变换
RxJava的变换有map,flatMap,concatMap,switchMap等等,这里介绍一下最常用的map方法。
先来看一个例子(示例代码中根据拼音搜索城市的例子):
mSubscription = mPublishSubject
.debounce(400, TimeUnit.MILLISECONDS)
.observeOn(Schedulers.io())
.map(new Func1&() {
public List call(String s) {
return serverHelper.searchCity(s);
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<list&() {
public void onCompleted() {
public void onError(Throwable e) {
public void onNext(List strings) {
handleSearchResults(strings);
从这个例子可以看到map方法根据传入的数据会返回自己想要的数据。可以理解为根据输入返回输出,数据处理的过程在map里面发生,数据返回的格式由自己定义。map返回的数据传送到subscribe订阅的observer中的onNext方法中,在onNext方法中可以做界面数据绑定等操作。map里面封装的new Func1函数是带有返回值的函数。也可以用下面的方式处理map返回结果:
mSubscription = mPublishSubject
.debounce(400, TimeUnit.MILLISECONDS)
.observeOn(Schedulers.io())
.map(new Func1&() {
public List call(String s) {
return serverHelper.searchCity(s);
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<list&() {
public void call(List strings) {
subscribe中封装的new Action1函数即是对new Func1函数返回值的响应,它是不带返回值的。可以在call方法里面做一些UI操作。
细心的你可能还会发型一个方法,debounce方法。在这个例子中,程序会监听用户输入的内容,当用户每次输入完,程序会异步查找匹配城市信息,为了避免一些不必要的匹配,这里设置debounce的时间为400毫秒,意思是每次用户输入完毕400毫秒后程序异步执行开始匹配城市信息。
好了,关于RxJava的介绍到此就结束啦。
五、RxAndroid示例讲解
1、RxAndroid包引入
compile &#39;io.reactivex:rxandroid:1.1.0&#39;
compile &#39;io.reactivex:rxjava:1.1.0&#39;
2、示例介绍
Example1Activity源码,RxJava简单示例:
* RxAndroid同步加载示例
public class Example1Activity extends Activity {
private RecyclerV
private SimpleStringA
private ProgressB
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
configureLayout();
createObservable();
private void createObservable() {
Observable<list& observer = Observable.just(getArrays());
observer.subscribe(new Observer<list&() {
public void onCompleted() {
public void onError(Throwable e) {
public void onNext(List strings) {
adapter.setStrings(strings);
private void configureLayout() {
setContentView(R.layout.activity1_rxandroid);
recyclerview = (RecyclerView) findViewById(R.id.recyleview);
progressbar = (ProgressBar) findViewById(R.id.loader);
recyclerview.setLayoutManager(new LinearLayoutManager(Example1Activity.this));
adapter = new SimpleStringAdapter(Example1Activity.this);
recyclerview.setAdapter(adapter);
progressbar.setVisibility(View.GONE);
private static List getArrays(){
List list = new ArrayList&&();
list.add("aaaa");
list.add("bbbb");
list.add("cccc");
list.add("dddd");
}</list</list
Example4Activity源码,RxJava异步加载,实现网络数据请求,显示到RecyclerView:
* RxAndroid异步加载示例
public class Example4Activity extends Activity {
private RecyclerV
private BeautyA
private ProgressB
private PublishSubject mPublishS
private Subscription mS
private List beautyList = new ArrayList&&();
private int pageIndex = 1;
private int pageSize = 10;
private boolean isLastPage =
private int lastVisibleItem = 0;
private LinearLayoutManager linearLayoutM
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
configureLayout();
createObserver();
recyclerview.setOnScrollListener(new RecyclerView.OnScrollListener() {
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE
&& lastVisibleItem + 1 == adapter.getItemCount()) {
//根据类目网络请求数据
if(!isLastPage){
page.setPageIndex(pageIndex);
mPublishSubject.onNext(page);
protected void onDestroy() {
super.onDestroy();
if (mSubscription != null && !mSubscription.isUnsubscribed()) {
mSubscription.unsubscribe();
private void createObserver() {
page = new Page(pageIndex,pageSize);
mPublishSubject = PublishSubject.create();
mSubscription = mPublishSubject
//指定subscribe发生在io线程
.observeOn(Schedulers.io())
.map(new Func1&() {
public List call(Page page) {
//网络数据请求
List list = ServerHelper.getBeautyList(page.getPageIndex(),page.getPageSize());
if(list.size() == pageSize){
pageIndex ++;
isLastPage =
}else if(list.size() & pageSize){
isLastPage =
//指定subscribe回调发生在UI线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<list&() {
public void onCompleted() {
public void onError(Throwable e) {
public void onNext(List beautyList) {
displayRecyclerView(beautyList);
mPublishSubject.onNext(page);
private void displayRecyclerView(List list) {
beautyList.addAll(list);
progressbar.setVisibility(View.GONE);
adapter.notifyDataSetChanged();
private void configureLayout() {
setContentView(R.layout.activity1_rxandroid);
progressbar = (ProgressBar) findViewById(R.id.loader);
recyclerview = (RecyclerView) findViewById(R.id.recyleview);
linearLayoutManager = new LinearLayoutManager(Example4Activity.this, LinearLayoutManager.VERTICAL,false);
recyclerview.setLayoutManager(linearLayoutManager);
adapter = new BeautyAdapter(beautyList,Example4Activity.this);
recyclerview.setAdapter(adapter);
recyclerview.addOnItemTouchListener(new OnRecyclerViewClickListener(recyclerview) {
protected void onItemClick(RecyclerView.ViewHolder viewHolder) {
Toast.makeText(Example4Activity.this,viewHolder.getLayoutPosition()+"",Toast.LENGTH_SHORT).show();
Example3Acticity源码,介绍了RxJava map的使用,根据用户输入城市拼音返回城市列表:
public class Example3Activity extends Activity {
private EditText mSearchI
private TextView mNoResultsI
private RecyclerView mSearchR
private SimpleStringAdapter mSearchResultsA
private PublishSubject mPublishS
private Subscription mS
private ServerHelper serverH
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
configureLayout();
createObservables();
listenToSearchInput();
private void listenToSearchInput() {
mSearchInput.addTextChangedListener(new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
public void onTextChanged(CharSequence s, int start, int before, int count) {
mPublishSubject.onNext(s.toString());
public void afterTextChanged(Editable s) {
private void createObservables() {
mPublishSubject = PublishSubject.create();
mSubscription = mPublishSubject
.debounce(400, TimeUnit.MILLISECONDS)
.observeOn(Schedulers.io())
.map(new Func1&() {
public List call(String s) {
return serverHelper.searchCity(s);
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<list&() {
public void onCompleted() {
public void onError(Throwable e) {
public void onNext(List strings) {
handleSearchResults(strings);
private void handleSearchResults(List cities) {
if (cities.isEmpty()) {
showNoSearchResults();
showSearchResults(cities);
private void showNoSearchResults() {
mNoResultsIndicator.setVisibility(View.VISIBLE);
mSearchResults.setVisibility(View.GONE);
private void showSearchResults(List cities) {
mNoResultsIndicator.setVisibility(View.GONE);
mSearchResults.setVisibility(View.VISIBLE);
mSearchResultsAdapter.setStrings(cities);
private void configureLayout() {
setContentView(R.layout.activity_3_example);
mSearchInput = (EditText) findViewById(R.id.search_input);
mNoResultsIndicator = (TextView) findViewById(R.id.no_results_indicator);
mSearchResults = (RecyclerView) findViewById(R.id.search_results);
mSearchResults.setLayoutManager(new LinearLayoutManager(this));
mSearchResultsAdapter = new SimpleStringAdapter(this);
mSearchResults.setAdapter(mSearchResultsAdapter);
serverHelper = new ServerHelper(Example3Activity.this);
protected void onDestroy() {
super.onDestroy();
if (mSubscription != null && !mSubscription.isUnsubscribed()) {
mSubscription.unsubscribe();
对了,每次事件注销不要忘了注销subscription:
protected void onDestroy() {
super.onDestroy();
if (mSubscription != null && !mSubscription.isUnsubscribed()) {
mSubscription.unsubscribe();
使用RxAndroid的感受,网络请求数据加载显示速度会更快,数据异步加载的过程被流程化,代码更简洁,逻辑更清晰。}

我要回帖

更多关于 王者荣耀闪退怎么解决 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信