Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android RxJava NetworkOnMainThread订阅时发生异常_Android_Rx Java_Rx Java2 - Fatal编程技术网

Android RxJava NetworkOnMainThread订阅时发生异常

Android RxJava NetworkOnMainThread订阅时发生异常,android,rx-java,rx-java2,Android,Rx Java,Rx Java2,我试图调用API并将数据添加到我的LiveData中,但在订阅之后,我在OnError中获得MainThreadException。尝试了不同的调度程序,但没有成功。从onError添加stacktrace private void pullLocation(){ myLocationService.getLocation() .flatMapSingle(new Function<Location, Single<DistanceResponseM

我试图调用API并将数据添加到我的LiveData中,但在订阅之后,我在OnError中获得MainThreadException。尝试了不同的调度程序,但没有成功。从onError添加stacktrace

private void pullLocation(){

    myLocationService.getLocation()
            .flatMapSingle(new Function<Location, Single<DistanceResponseModel>>() {
                @Override
                public Single<DistanceResponseModel> apply(@NonNull Location location) throws Exception {
                    return distanceRepository.distanceResponseAPI(location.getLatitude() + "," + location.getLongitude(), getDestinations(), "my_google_api_key");
                }
            })

            .subscribeOn(Schedulers.io())
            .observeOn(Schedulers.io())
            .subscribe(new Subscriber<DistanceResponseModel>() {
        @Override
        public void onSubscribe(Subscription s) {
            Log.d(TAG, "onSubscribe in DistanceViewModel called. ");
        }

        @Override
        public void onNext(DistanceResponseModel distanceResponseModel) {
            distanceLiveData.postValue(distanceResponseModel);
            Log.d(TAG, "onNext in DistanceViewModel called. ");
        }

        @Override
        public void onError(Throwable t) {
            Log.e("YOUR_APP_LOG_TAG", "I got an error:", t);
        }

        @Override
        public void onComplete() {
            Log.d(TAG, "onComplete in DistanceViewModel called. ");
        }
    });
}
这是我得到的位置:

public class MyLocationServiceClass implements MyLocationService {

    PublishProcessor<Location> stream = PublishProcessor.create();
    LocationListener listener = new LocationListener() {
        @Override
        public void onLocationChanged(@NonNull Location location) {
            stream.onNext(location);
            Log.d(TAG, "onLocationChanged: stream.onNext(location) called");
        }

        @Override
        public void onProviderEnabled(@NonNull String provider) {

        }

        @Override
        public void onProviderDisabled(@NonNull String provider) {

        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }
    };

    private LocationManager locationManager;
    private boolean flag;
    private Context context;

    public MyLocationServiceClass(Context context, LocationManager locationManager, boolean flag) {
        this.context = context;
        this.locationManager = locationManager;
        this.flag = flag;

    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void onStart() {
        if (flag) {
            start();
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void onStop() {
        locationManager.removeUpdates(listener);
    }


    @Override
    public Flowable<Location> getLocation() {
        return stream.hide();
    }

    @Override
    public void start() {
        long minTimeMs = 10000;
        float minDistanceM = 5.5F;


        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }
        Log.d(TAG, "start(): requestLocationUpdates called.");
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTimeMs, minDistanceM, listener);

    }

    @Override
    public void updatePermission(boolean newState) {
        flag = newState;
    }

public interface MyLocationService extends LifecycleObserver {

    Flowable<Location> getLocation();

    void start();
    void updatePermission(boolean newState);
}
公共类MyLocationServiceClass实现MyLocationService{
PublishProcessor流=PublishProcessor.create();
LocationListener=新建LocationListener(){
@凌驾
public void onLocationChanged(@NonNull Location){
stream.onNext(位置);
Log.d(标记“onLocationChanged:stream.onNext(location)called”);
}
@凌驾
public void onProviderEnabled(@NonNull字符串提供程序){
}
@凌驾
public void onProviderDisabled(@NonNull字符串提供程序){
}
@凌驾
public void onStatusChanged(字符串提供程序、int状态、Bundle extra){
}
};
私人场所经理场所经理;
私有布尔标志;
私人语境;
公共MyLocationServiceClass(上下文上下文、LocationManager LocationManager、布尔标志){
this.context=上下文;
this.locationManager=locationManager;
this.flag=flag;
}
@onLiFeCycleeEvent(Lifecycle.Event.ON_START)
void onStart(){
国际单项体育联合会(旗){
start();
}
}
@onLiFeCycleeEvent(Lifecycle.Event.ON_STOP)
void onStop(){
locationManager.RemoveUpdate(侦听器);
}
@凌驾
公共可流动getLocation(){
返回stream.hide();
}
@凌驾
公开作废开始(){
长最小时间=10000;
浮动距离M=5.5F;
if(ActivityCompat.checkSelfPermission(context,Manifest.permission.ACCESS\u FINE\u LOCATION)!=PackageManager.permission\u已授予和&ActivityCompat.checkSelfPermission(context,Manifest.permission.ACCESS\u LOCATION)!=PackageManager.permission\u已授予){
返回;
}
d(标记“start():requestLocationUpdates called.”);
locationManager.RequestLocationUpdate(locationManager.GPS_提供程序、Mintimes、MindStatancem、侦听器);
}
@凌驾
public void updatePermission(布尔newState){
flag=新闻状态;
}
公共接口MyLocationService扩展LifecycleObserver{
可流动的getLocation();
void start();
void updatePermission(布尔newState);
}
你知道会是什么吗?如果你想知道更多细节,请告诉我。希望这能有所帮助

带完整代码的回购:

问题 调用
distanceRepository.distanceResponseAPI(location.getLatitude()+,“+location.getLatitude(),getDestinations(),“my_google_api_key”)
时,onError(NetworkOnMainThreadException)会传播到订阅服务器

为什么会抛出异常? 禁止在UI Eventloop上执行网络请求,以免阻塞UI

为什么订阅没有帮助?
subscribeOn
调用给定调度程序上游操作符的subscribeActual方法。在您的情况下,从IO调度程序中的工作线程调用subscribe for
flatMapSingle
操作符。
flatMapSingle
在同一线程上调用
myLocationService.getLocation()

正如您在stacktrace中看到的,从
getLocation
返回的onNext from source observable是从UI线程发出的

    at io.reactivex.processors.PublishProcessor$PublishSubscription.onNext(PublishProcessor.java:361)
    at io.reactivex.processors.PublishProcessor.onNext(PublishProcessor.java:244)
    at com.example.compass.viewModels.MyLocationServiceClass$1.onLocationChanged(MyLocationServiceClass.java:35)
    at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:292)
    at android.location.LocationManager$ListenerTransport.-wrap0(Unknown Source:0)
    at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:237)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:164)
该值通过调用线程(UI线程)上的onNext发出,因为回调是从UI线程调用的。
flatMapSingle
操作符也在调用UI线程上调用。它订阅lambda返回的
Single
,并在调用线程上订阅。因此UI线程调用UI线程上的网络请求,异常由ndroid运行时。
SubscribeOn
不确保onNext在给定的
调度程序上处于下游。它只确保订阅在此线程中发生。在您的情况下,您的源可观察对象将在UI线程上收到安卓运行时的通知

解决方案 在myLocationService.getLocation()之后使用
observeOn
以将线程从一个操作符切换到另一个操作符。
observeOn
确保
onNext
调用下游发生在给定的调度程序上。因此,
flatMapSingle
中的内部流订阅将发生在给定的调度程序工作线程上,而不是ui线程上。您也可以应用
flatMapSingle
中的
Single
上订阅。这将确保网络调用将在给定的调度程序工作线程上发生

        .flatMapSingle(new Function<Location, Single<DistanceResponseModel>>() {
            @Override
            public Single<DistanceResponseModel> apply(@NonNull Location location) throws Exception {
                return distanceRepository.distanceResponseAPI(location.getLatitude() + "," + location.getLongitude(), getDestinations(), "my_google_api_key")
                                         .subscribeOn(Schedulers.io());
            }
        })
.flatMapSingle(新函数(){
@凌驾
公共单应用(@NonNull Location)引发异常{
返回distanceRepository.distanceResponseAPI(location.getLatitude()+”、“+location.getLatitude()、getDestinations()、“my_google_api_key”)
.subscribeOn(Schedulers.io());
}
})
进一步阅读

你能发布stacktrace吗?好吧,我的代码已经编译好了,所以没有错误。但是,当我记录一个错误时,抛出了NetworkOnMainThreadException。不确定粘贴整个日志是否有用。查看抛出异常的位置会很有趣。记录stacktrace,而不仅仅是异常的名称。而在这里,您还可以包括
getLocation()
的关键部分。请尝试
distanceRepository.distanceResponseAPI(…).subscribeOn(Schedulers.io())
直接。在
flatMap
之后应用它不会影响设置中的lambda。@akarnokd,该死的。我太晚了。是的,似乎flatMapSingle是问题的根本原因(例如stacktrace:
可流动。可流动flatMapSingle
        .flatMapSingle(new Function<Location, Single<DistanceResponseModel>>() {
            @Override
            public Single<DistanceResponseModel> apply(@NonNull Location location) throws Exception {
                return distanceRepository.distanceResponseAPI(location.getLatitude() + "," + location.getLongitude(), getDestinations(), "my_google_api_key")
                                         .subscribeOn(Schedulers.io());
            }
        })