Cách tôi nghĩ về nó là bạn sử dụng flatMap
khi hàm bạn muốn đặt bên trong map()
trả về một Observable
. Trong trường hợp bạn vẫn có thể cố gắng sử dụng map()
nhưng nó sẽ không thực tế. Hãy để tôi cố gắng giải thích tại sao.
Nếu trong trường hợp như vậy bạn quyết định gắn bó map
, bạn sẽ nhận được một Observable<Observable<Something>>
. Ví dụ: trong trường hợp của bạn, nếu chúng tôi sử dụng thư viện RxGson tưởng tượng, đã trả về một phương thức Observable<String>
từ nó toJson()
(thay vì chỉ trả về a String
), nó sẽ trông như thế này:
Observable.from(jsonFile).map(new Func1<File, Observable<String>>() {
@Override public Observable<String>> call(File file) {
return new RxGson().toJson(new FileReader(file), Object.class);
}
}); // you get Observable<Observable<String>> here
Tại thời điểm này, nó sẽ khá khó khăn để subscribe()
có thể quan sát như vậy. Bên trong nó, bạn sẽ nhận được một Observable<String>
cái mà bạn sẽ cần subscribe()
để nhận được giá trị. Đó là không thực tế hoặc tốt đẹp để xem xét.
Vì vậy, để làm cho nó hữu ích, một ý tưởng là "làm phẳng" điều có thể quan sát được này (bạn có thể bắt đầu xem tên _flat_Map đến từ đâu). RxJava cung cấp một vài cách để làm phẳng các vật thể quan sát và vì đơn giản, hãy cho rằng hợp nhất là những gì chúng ta muốn. Hợp nhất về cơ bản có một loạt các vật quan sát và phát ra bất cứ khi nào chúng phát ra. (Rất nhiều người sẽ cho rằng chuyển đổi sẽ là một mặc định tốt hơn. Nhưng nếu bạn chỉ phát ra một giá trị, thì dù sao đi nữa cũng không thành vấn đề.)
Vì vậy, sửa đổi đoạn trích trước của chúng tôi, chúng tôi sẽ nhận được:
Observable.from(jsonFile).map(new Func1<File, Observable<String>>() {
@Override public Observable<String>> call(File file) {
return new RxGson().toJson(new FileReader(file), Object.class);
}
}).merge(); // you get Observable<String> here
Điều này hữu ích hơn rất nhiều, vì đăng ký vào đó (hoặc ánh xạ hoặc lọc, hoặc ...) bạn chỉ nhận được String
giá trị. (Ngoài ra, hãy nhớ rằng, biến thể như vậy merge()
không tồn tại trong RxJava, nhưng nếu bạn hiểu ý tưởng hợp nhất thì tôi hy vọng bạn cũng hiểu cách thức hoạt động của nó.)
Vì vậy, về cơ bản bởi vì điều đó merge()
có lẽ chỉ hữu ích khi nó thành công map()
trở lại có thể quan sát được và do đó bạn không phải gõ lại nhiều lần, flatMap()
được tạo ra như một cách viết tắt. Nó áp dụng chức năng ánh xạ như bình thường map()
, nhưng sau đó thay vì phát ra các giá trị được trả về, nó cũng "làm phẳng" (hoặc hợp nhất) chúng.
Đó là trường hợp sử dụng chung. Nó hữu ích nhất trong một cơ sở mã sử dụng Rx allover vị trí và bạn đã có nhiều phương thức trả về các vật quan sát, mà bạn muốn xâu chuỗi với các phương thức khác trả về các vật quan sát.
Trong trường hợp sử dụng của bạn, nó cũng có ích, bởi vì map()
chỉ có thể chuyển đổi một giá trị được phát ra onNext()
thành một giá trị khác được phát ra onNext()
. Nhưng nó không thể chuyển đổi nó thành nhiều giá trị, không có giá trị nào hoặc có lỗi. Và như akarnokd đã viết trong câu trả lời của anh ấy (và nhớ rằng anh ấy thông minh hơn tôi rất nhiều, có lẽ nói chung, nhưng ít nhất là khi nói đến RxJava), bạn không nên ném ngoại lệ từ bạn map()
. Vì vậy, thay vào đó bạn có thể sử dụng flatMap()
và
return Observable.just(value);
khi mọi việc suôn sẻ, nhưng
return Observable.error(exception);
khi một cái gì đó thất bại.
Xem câu trả lời của anh ấy cho một đoạn hoàn chỉnh: https://stackoverflow.com/a/30330772/1402641
subscriber.onError()
vv Tất cả các ví dụ tôi đã thấy có lỗi định tuyến theo cách đó. Điều đó không quan trọng?