在flatMap中出现NetworkOnMainThreadException异常

5

我刚开始接触rxjava或者rxandroid,并且想要用observablesubscriber来改善我的AsyncTask和回调地狱。但是我遇到了一个问题:我需要向我的数据库发起两个请求。

第一个请求的响应将会成为第二个请求的结果。我尝试使用flatMap来解决这个问题。第一个请求的返回值没问题,但是第二个请求却报错:NetworkOnMainThreadException

我知道请求是在主线程上执行的,但是为什么呢?我尝试在flatMap之前添加subscribeOn(Schedulers.io()),但结果还是一样。您能帮助我解决这个问题并解释我做错了什么吗?非常感谢。下面是我的代码......

private void getFavouriteList(){
    Observable.create((Observable.OnSubscribe<PaginatedScanList<UserDO>>) subscriber -> {
        final Map<String, AttributeValue> filterExpressionAttributeValues = new HashMap<>();
        filterExpressionAttributeValues
                .put(":val1", new AttributeValue().withS(sharedPreferences.getString("socialId", "")));
        final DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()
                .withFilterExpression("socialId = :val1")
                .withExpressionAttributeValues(filterExpressionAttributeValues);
        PaginatedScanList<UserDO> result = dynamoDBMapper.scan(UserDO.class, scanExpression);
        Log.d(TAG, "first result size " + result.size());
        subscriber.onNext(result);
        subscriber.onCompleted();
    })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .filter(result -> {
                if(result.isEmpty()) {
                    Toast.makeText(context, "Can not find user", Toast.LENGTH_SHORT).show();
                    return false;
                }
                return true;
            })
            .flatMap(user -> Observable.from(user.get(0).getFavourites()))
            .subscribeOn(Schedulers.io())
            .flatMap(result -> {
                final Map<String, AttributeValue> filterExpressionAttributeValues = new HashMap<>();
                filterExpressionAttributeValues
                        .put(":val1", new AttributeValue().withS(result));
                filterExpressionAttributeValues
                        .put(":val2", new AttributeValue().withN("1"));
                final DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()
                        .withFilterExpression("productId = :val1 and selling = :val2")
                        .withExpressionAttributeValues(filterExpressionAttributeValues);
                PaginatedScanList<ProductDO> res = dynamoDBMapper.scan(ProductDO.class, scanExpression);
                Log.d(TAG, "second result size " + res.size());
                return Observable.from(res);
            })
            .subscribe(new Subscriber<ProductDO>() {
                @Override
                public void onCompleted() {
                    favouriteProgressBar.setVisibility(View.INVISIBLE);
                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                    favouriteProgressBar.setVisibility(View.INVISIBLE);
                }

                @Override
                public void onNext(ProductDO productDO) {
                    Log.d(TAG, "productId " + productDO.getProductId());
                    product.add(productDO);
                    adapter.notifyDataSetChanged();
                }
            });
}

https://dev59.com/-mw15IYBdhLWcg3w3vpe - Konstantin Pribluda
1个回答

4

.observeOn(AndroidSchedulers.mainThread())移动到您的subscribe之前。

附:除非没有其他选择,否则不应使用Observable.create()

编辑以修复过滤器中的Toast问题。

private void getFavouriteList(){
    Observable.create((Observable.OnSubscribe<PaginatedScanList<UserDO>>) subscriber -> {
        final Map<String, AttributeValue> filterExpressionAttributeValues = new HashMap<>();
        filterExpressionAttributeValues
                .put(":val1", new AttributeValue().withS(sharedPreferences.getString("socialId", "")));
        final DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()
                .withFilterExpression("socialId = :val1")
                .withExpressionAttributeValues(filterExpressionAttributeValues);
        PaginatedScanList<UserDO> result = dynamoDBMapper.scan(UserDO.class, scanExpression);
        Log.d(TAG, "first result size " + result.size());
        subscriber.onNext(result);
        subscriber.onCompleted();
    })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .filter(result -> {
                if(result.isEmpty()) {
                    Toast.makeText(context, "Can not find user", Toast.LENGTH_SHORT).show();
                    return false;
                }
                return true;
            })
            .observeOn(Schedulers.io())
            .flatMap(user -> Observable.from(user.get(0).getFavourites()))
            .flatMap(result -> {
                final Map<String, AttributeValue> filterExpressionAttributeValues = new HashMap<>();
                filterExpressionAttributeValues
                        .put(":val1", new AttributeValue().withS(result));
                filterExpressionAttributeValues
                        .put(":val2", new AttributeValue().withN("1"));
                final DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()
                        .withFilterExpression("productId = :val1 and selling = :val2")
                        .withExpressionAttributeValues(filterExpressionAttributeValues);
                PaginatedScanList<ProductDO> res = dynamoDBMapper.scan(ProductDO.class, scanExpression);
                Log.d(TAG, "second result size " + res.size());
                return Observable.from(res);
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<ProductDO>() {
                @Override
                public void onCompleted() {
                    favouriteProgressBar.setVisibility(View.INVISIBLE);
                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                    favouriteProgressBar.setVisibility(View.INVISIBLE);
                }

                @Override
                public void onNext(ProductDO productDO) {
                    Log.d(TAG, "productId " + productDO.getProductId());
                    product.add(productDO);
                    adapter.notifyDataSetChanged();
                }
            });
}

谢谢,这真的很有帮助。Observable.create()有什么问题? - Alex Khotiun
使用Observable.create()很容易犯错。请参阅此处以获取替代方案的文档。 - JohnWowUs
当我在subscribe之前放置.observeOn(AndroidSchedulers.mainThread())时,过滤器中的Toast不起作用,会出现android.view.ViewRootImpl$CalledFromWrongThreadException的问题。 - Alex Khotiun
第二个.subscribeOn(Schedulers.io())是不必要的,除了浪费一个线程外,没有任何实际效果。 - akarnokd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接