2015-05-15 9 views
26

मैं 2 नेटवर्क कॉल एक दूसरे के बाद निष्पादित करना चाहता हूं। दोनों नेटवर्क कॉल अवलोकन योग्य वापसी। दूसरा कॉल पहली कॉल के सफल परिणाम से डेटा का उपयोग करता है, दूसरे कॉल के सफल परिणाम में विधि से पहले पहले और दूसरे कॉल के सफल परिणाम का उपयोग करती है। इसके अलावा मुझे दोनों पर "घटनाओं" को अलग-अलग करने में सक्षम होना चाहिए। कैसे मैं नीचे दिए गए उदाहरण में इस तरह से परहेज कॉलबैक नरक को प्राप्त कर सकते हैं:चेन दो रेट्रोफिट वेरिएबल्स w/RxJava

 API().auth(email, password) 
      .subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(new Action1<AuthResponse>() { 
       @Override 
       public void call(final AuthResponse authResponse) { 
        API().getUser(authResponse.getAccessToken()) 
          .subscribe(new Action1<List<User>>() { 
           @Override 
           public void call(List<User> users) { 
            doSomething(authResponse, users); 
           } 
          }, new Action1<Throwable>() { 
           @Override 
           public void call(Throwable throwable) { 
            onErrorGetUser(); 
           } 
          }); 
       } 
      }, new Action1<Throwable>() { 
       @Override 
       public void call(Throwable throwable) { 
        onErrorAuth(); 
       } 
      }); 

मैं ज़िप के बारे में पता है, लेकिन मैं करने के लिए "Combiner वर्ग" बनाने से बचने चाहते हैं।

अद्यतन 1. akarnokd के जवाब को लागू करने की कोशिश की:

  API() 
      .auth(email, password) 
      .subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .flatMap(authResponse -> API() 
        .getUser(authResponse.getAccessToken()) 
        .doOnError(throwable -> { 
         getView().setError(processFail(throwable)); 
        }), ((authResponse, users) -> { 
       // Ensure returned user is the which was authenticated 
       if (authResponse.getUserId().equals(users.get(0).getId())) { 
        SessionManager.getInstance().initSession(email, password, authResponse.getAccessToken(), users.get(0)); 
        getView().toNews(); 
       } else { 
        getView().setError(R.string.something_went_wrong); 
       } 
      })); 

हालांकि flatMap अंदर विधि संकलक यह authResponse और उपयोगकर्ताओं (authResponse.getAccessToken(), users.get(0) आदि) के तरीकों को हल नहीं कर सकता कहते हैं। मैं आरएक्स प्रोग्रामिंग और लैम्बडास के लिए नया हूं - कृपया मुझे बताएं कि समस्या क्या है। वैसे भी कोड अब बहुत साफ दिखता है।

अद्यतन 2.

API() 
      .auth(email, password) 
      .subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .doOnError(throwable -> getView().setError(processFail(throwable))) 
      .flatMap((AuthResponse authResponse) -> API() 
        .getUser(authResponse.getAccessToken()) 
        .doOnError(throwable -> getView().setError(processFail(throwable))), ((AuthResponse authResponse, List<User> users) -> { 
          // Ensure returned user is the which was authenticated 
          if (authResponse.getUserId().equals(users.get(0).getId())) { 
           SessionManager.getInstance().initSession(email, password, authResponse.getAccessToken(), users.get(0)); 
           getView().toNews(); 
          } 
          return Observable.just(this); 
      })); 

इस तरह यह किया है, लेकिन अब मेरा नेटवर्क कॉल बिल्कुल क्रियान्वित नहीं कर रहे हैं।

+0

मैं एक IDE से दूर हूँ, लेकिन मुझे लगता है कि त्रुटि लैम्ब्डा पैरामीटर नाम संघर्ष की वजह से है । – akarnokd

+1

ऐसा लगता है कि आप अब सदस्यता नहीं ले रहे हैं। सुनिश्चित करें कि आप श्रृंखला के नीचे सदस्यता() सदस्यता लें। –

उत्तर

10

एंथोनी आर के जवाब के अलावा, वहाँ एक flatMap अधिभार जो आप के लिए एक Func2 और जोड़े अपनी प्राथमिक और चपटा मान लेता है। इसके अलावा, onErrorXXX और त्रुटि हेरफेर के लिए onExceptionXXX ऑपरेटरों को देखो, और अपने पहले और दूसरे observables के साथ उन्हें श्रृंखला

first.onErrorReturn(1) 
.flatMap(v -> service(v).onErrorReturn(2), (a, b) -> a + b); 
+0

धन्यवाद, मैं इसे आजमाउंगा। एंड्रॉइड के लिए रेट्रोलंबडा का उपयोग कर कोई सीमाएं हैं? – localhost

+0

हाँ, मेरा उदाहरण flatMap() के उस अधिभार का उपयोग कर रहा था। onErrorReturn काम कर सकता था और सिर्फ अशक्त वापसी, लेकिन फिर flatMap में समारोह() दूसरा प्रत्यक्ष लौटने से पहले एक अशक्त नियंत्रण रखने के करने के लिए होगा, मुझे लगता है। मुझे यकीन है कि के किसी भी प्रश्न में मूल कोड की तुलना में अधिक स्पष्ट हो जाएगा नहीं कर रहा हूँ। एंड्रॉयड पर retrolambda उपयोग करने के साथ –

+0

और सीमाओं यहाँ प्रलेखित रहे हैं: https://github.com/evant/gradle-retrolambda#known-issues –

15

क्या आपने flatMap() में देखा है? यदि आपके प्रतिद्वंद्विता (या ज़िप()) को दो वस्तुओं को रखने के लिए अनावश्यक कक्षा बनाने की आवश्यकता है, android.util.Pair एक उत्तर हो सकता है। मुझे यकीन नहीं है कि आप जिस त्रुटि को संभालने की तलाश में हैं, उसे कैसे प्राप्त करें।

 API().auth(email, password) 
     .subscribeOn(Schedulers.newThread()) 
     .observeOn(AndroidSchedulers.mainThread()) 
     .flatMap(new Func1<AuthResponse, Observable<List<User>>>() { 
      @Override 
      public Observable<List<User>> call(AuthResponse authResponse) { 
      return API().getUser(authResponse.getAccessToken()); 
      } 
     }, new Func2<AuthResponse, List<User>, Pair<AuthResponse, List<User>>>() { 
      @Override 
      public Pair<AuthResponse, List<User>> call(AuthResponse authResponse, List<User> users) { 
      return new Pair<>(authResponse, users); 
      } 
     }).subscribe(new Action1<Pair<AuthResponse, List<User>>>() { 
      @Override 
      public void call(Pair<AuthResponse, List<User>> pair) { 
      doSomething(pair.first, pair.second); 
      } 
     }, new Action1<Throwable>() { 
      @Override 
      public void call(Throwable throwable) { 
      // not sure how to tell which one threw the error 
      } 
     }); 
+0

क्या आप मुझे फ्लैटमैप के साथ एक उदाहरण दे सकते हैं? जोड़ी के लिए, क्या होगा यदि यह 2 से अधिक वस्तुओं है? – localhost

+0

आप Func9 पर Func1 का उपयोग कर सकते हैं, एक FuncN भी है। – Aegis

+0

इस मामले में 'API()। GetUser (..) 'कॉल पृष्ठभूमि थ्रेड में नहीं चलेगा? – clu