Retrofit 2.0 और RxJava का उपयोग करके प्रतिक्रिया स्थिति कोड प्राप्त करें


107

मैं Retrofit 2.0 में अपग्रेड करने और अपने Android प्रोजेक्ट में RxJava को जोड़ने का प्रयास कर रहा हूं। मैं एक एपीआई कॉल कर रहा हूं और सर्वर से त्रुटि प्रतिक्रिया के मामले में त्रुटि कोड प्राप्त करना चाहता हूं।

Observable<MyResponseObject> apiCall(@Body body);

और RxJava कॉल में:

myRetrofitObject.apiCall(body).subscribe(new Subscriber<MyResponseObject>() {
        @Override
        public void onCompleted() {

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onNext(MyResponseObject myResponseObject) {
           //On response from server
        }
    });

रिट्रोफिट 1.9 में, रेट्रोफिटइर्र अभी भी मौजूद था और हम ऐसा करके स्थिति प्राप्त कर सकते थे:

error.getResponse().getStatus()

RxJava का उपयोग करके आप Retrofit 2.0 के साथ यह कैसे करते हैं?

जवाबों:


185

अपने जैसे एपीआई कॉल की घोषणा करने के बजाय:

Observable<MyResponseObject> apiCall(@Body body);

आप इसे इस तरह से घोषित कर सकते हैं:

Observable<Response<MyResponseObject>> apiCall(@Body body);

फिर आपके पास निम्नलिखित की तरह एक सब्सक्राइबर होगा:

new Subscriber<Response<StartupResponse>>() {
    @Override
    public void onCompleted() {}

    @Override
    public void onError(Throwable e) {
        Timber.e(e, "onError: %", e.toString());

        // network errors, e. g. UnknownHostException, will end up here
    }

    @Override
    public void onNext(Response<StartupResponse> startupResponseResponse) {
        Timber.d("onNext: %s", startupResponseResponse.code());

        // HTTP errors, e. g. 404, will end up here!
    }
}

तो, एक त्रुटि कोड के साथ सर्वर प्रतिक्रियाएं भी वितरित की जाएंगी onNextऔर आप कॉल करके कोड प्राप्त कर सकते हैं reponse.code()

http://square.github.io/retrofit/2.x/retrofit/retrofit/Response.html

संपादित करें: ठीक है, मैं अंत में ई-नूरी ने अपनी टिप्पणी में कहा है कि केवल 2xx कोड करने के लिए होगा onNext। हम दोनों सही हैं:

यदि कॉल इस तरह से घोषित किया जाता है:

Observable<Response<MyResponseObject>> apiCall(@Body body);

या यह भी

Observable<Response<ResponseBody>> apiCall(@Body body);

सभी प्रतिक्रियाएँ समाप्त हो जाएंगी onNext, चाहे उनका त्रुटि कोड कुछ भी हो। यह संभव है क्योंकि Responseरिट्रोफिट द्वारा एक वस्तु में सब कुछ लपेटा गया है ।

यदि, दूसरी ओर, कॉल इस तरह घोषित की जाती है:

Observable<MyResponseObject> apiCall(@Body body);

या यह

Observable<ResponseBody> apiCall(@Body body);

वास्तव में केवल 2xx प्रतिक्रियाएं ही जाएंगी onNext। बाकी सब कुछ एक में लपेटा जाएगा HttpExceptionऔर भेजा जाएगा onError। जो भी समझ में आता है, क्योंकि Responseआवरण के बिना , क्या उत्सर्जित किया जाना चाहिएonNext ? यह देखते हुए कि अनुरोध सफल नहीं था केवल समझदार चीज ही नहीं होगी null...


16
HTTP कोड 4xx की तलाश कर रहे लोगों के लिए वे ऑनएयर में HttpException के रूप में समाप्त हो जाएंगे। onNext में केवल 2xx होगा।
ई-नूरी

2
यह दिलचस्प है ... मैंने अभी फिर से जाँच की ( gist.github.com/DavidMihola/17a6ea373b9312fb723b ) और सभी कोड जिन्हें मैंने onNext404 सहित समाप्त करने की कोशिश की , आदि। मैंने Retrofit -2.0.0-Beta3 का उपयोग किया।
david.mihola 14

@ ई-नूरी: मैंने अपने उत्तर में एक पैराग्राफ जोड़ा है जो आपकी टिप्पणी को ध्यान में रखता है!
david.mihola

1
@ david.mihola यदि ऐड के माध्यम से रिट्रोफिट का निर्माण करें GsonConverterFactory, जैसा कि Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()), मूल प्रतिक्रिया कैसे प्राप्त करें?
हांगे.हु।

1
त्रुटि से निपटने के अलावा, मुझे लगता है कि आप शरीर के साथ आने वाले किसी भी प्रतिक्रिया हेडर का निरीक्षण करने में सक्षम होना चाहते हैं - यह केवल तभी संभव है जब आप प्राप्त करेंगे Response। मैं शायद ही कभी इसका उपयोग करता हूं - लेकिन मुझे लगता है कि यह जानना अच्छा है कि यह मौजूद है।
david.mihola

112

अंदर की विधि पर कोड प्राप्त करने के लिए इसे डाल दिया

((HttpException) e).code()

7
यह सबसे कम उत्तर में से एक हो सकता है जो मैंने एसओ में देखा है। यह जीनियस है। आप वह सब कुछ कर सकते हैं जो आपको प्रतिक्रिया के साथ करने की आवश्यकता हो सकती है HttpException। मैं RxJava का उपयोग कर रहा हूं और मुझे एक प्राप्त करने के बाद प्रतिक्रिया को पार्स करने की आवश्यकता है HTTP 400 BAD REQUEST। आपका बहुत बहुत धन्यवाद!
गैब्रियलओशिरो

29
बस यह सुनिश्चित करना सुनिश्चित करें कि क्या यह एक इंट्रॉफ़ HttpException है, क्योंकि NetworkErrors IOException होगी और स्थिति कोड नहीं है।
बेंजामिन मेसिंग

@BenjaminMesing से पालन करने के लिए NetworkError के बारे में कहा, यदि आप सदस्यता लेने से पहले अपने Rx में अधिक डाउनस्ट्रीम ऑपरेटर (मानचित्र / फ्लैटपाइप / फॉरएच आदि) कर रहे हैं, तो संभावित अपवाद प्रकारों की मेजबानी हो सकती है, और जरूरी नहीं कि इसमें कोई त्रुटि हो। नेटवर्क अनुरोध।
मार्क कीन

java.lang.ClassCastException: java.lang.Throwable को retrofit2 में नहीं डाला जा सकता। HttpException
किसी को कहीं

7

आप को ध्यान देना चाहिए के रूप में है कि Retrofit2 कोड के साथ सभी प्रतिक्रियाओं 2xx onNext () कॉलबैक और के बाकी हिस्सों से बुलाया जाएगा HTTP कोड 4xx की तरह, 5xx पर बुलाया जाएगा onError () , कॉलबैक का उपयोग कर Kotlin मैं गया है की तरह कुछ के साथ आया था इस onrror () में :

mViewReference?.get()?.onMediaFetchFinished(downloadArg)
  if (it is HttpException) {
    val errorCode = it.code()
    mViewReference?.get()?.onMediaFetchFailed(downloadArg,when(errorCode){
      HttpURLConnection.HTTP_NOT_FOUND -> R.string.check_is_private
      else -> ErrorHandler.parseError(it)
    })
  } else {
    mViewReference?.get()?.onMediaFetchFailed(downloadArg, ErrorHandler.parseError(it))
  }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.