मैं एंड्रॉइड में एमवीवीएम आर्किटेक्चर को लटकाने की कोशिश कर रहा हूं और इसके लिए नमूना ऐप पर काम कर रहा था। मैंने अभी के लिए रिपोजिटरी क्लास से परहेज किया है, यह चिंताओं को अलग करने से बच रहा है लेकिन मैं पहले व्यूमोडेल और लाइवडाटा की बेहतर समझ प्राप्त करना चाहता था। मेरे पास एक टुकड़ा है जहां मैं रेट्रोफिट और व्यूमोडेल इंस्टेंस का उपयोग करके नेटवर्क कॉल करता हूं। फिर उसी व्यूमोडेल ऑब्जेक्ट का उपयोग करके मैं एक ही कॉल करता हूं लेकिन विभिन्न पैरामीटर मानों के साथ। अब ऑन चेंज ट्रिगर किया गया है और जब मैं प्रतिक्रिया लॉग करता हूं (log.d का उपयोग करके) मुझे इसके अंदर पुरानी प्रतिक्रिया मिलती है। और कुछ मिलीसेकंड की देरी के बाद, HttpLoggingInterceptor नई प्रतिक्रिया लॉग करता है। मैंने बहुत सी चीजों की कोशिश की है लेकिन मैं यह नहीं समझ सकता कि क्या हो रहा है। इस मुद्दे की खोज करने पर, मुझे यह मिला: समझ में नहीं आता कि दिए गए उत्तर को कैसे लागू किया जाए।

कोड:
एपी इंटरफेस

public interface ApiInterface {
@GET("fetch")
Call<String> fetchData(@Query("param1") String param1,
                       @Query("param2") String param2,
                       @Query("param3") String param3,
                       @Query("param4") String param4,
                       @Query("param5") String param5);

व्यूमॉडलडेटा

public class ViewModelData extends ViewModel {
private MutableLiveData<String> data = new MutableLiveData<>();

private final String TAG = getClass().getSimpleName();

public LiveData<String> getData(String param1, String param2, String param3, String param4,
                                        String param5){
    loadData(param1, param2, param3, param4, param5);

    return data;
}

private void loadData(String param1, String param2, String param3, String param4,
                              String param5){
    Retrofit retrofit = HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);

    OkHttpClient okHttpClientGet = new OkHttpClient.Builder()
            .addInterceptor(logging)
            .build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(ScalarsConverterFactory.create())
            .client(okHttpClientGet)
            .build();
    ApiInterface apiInterface = retrofit.create(ApiInterface.class);

    Call<String> call = apiInterface.fetchData(param1, param2, param3, param4, param5);

    call.enqueue(new Callback<String>() {
        @Override
        public void onResponse(Call<String> call, Response<String> response) {
            if(response.isSuccessful()){
                Log.v(TAG, "onResponse: " + response.body());
                data.postValue(response.body());
            }else{
                try {
                    String errorBody = response.errorBody().string();
                    Log.e(TAG, "onResponse: " + errorBody);
                    data.postValue(errorBody);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

        @Override
        public void onFailure(Call<String> call, Throwable t) {
            Log.e(TAG, "onFailure: " + t.getMessage());
        }
    });
}

FragmentTest (यह एक फ़ंक्शन के अंदर है जिसे मैंने परिभाषित किया है जिसे एक बटन के क्लिक पर बुलाया जा रहा है)

viewmodelData.getData("param1", "param2", "param3",
            "param4", "param5")
                .observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(String s) {
                Log.v("TAG", "onChanged: " + s);

                Gson gson = new Gson();
                JsonObject root = gson.fromJson(s, JsonObject.class);
                
                //parsing response...
            }
        });

ViewModel उदाहरण इस प्रकार बनाया गया है:

viewmodelData = new ViewModelProvider(this).get(ViewModelData.class);

मैं किसी भी मदद की सराहना करता हूं क्योंकि मैं पिछले कुछ समय से इस पर अटका हुआ हूं।

0
Uday Vig 25 सितंबर 2021, 20:59
ऐसा लगता है कि आप प्रत्येक कॉल के लिए एक नया रेट्रोफिट ऑब्जेक्ट बनाते हैं (क्यों?) साथ ही, एक रिटर्न न्यू रेट्रोफिट.बिल्डर () बाकी कोड को ब्लॉक कर रहा है। हो सकता है कि आपने कोड गलत तरीके से चिपकाया हो?
 – 
gioravered
25 सितंबर 2021, 21:29
हाँ मैंने कोड गलत तरीके से चिपकाया है। इसे इंगित करने के लिए धन्यवाद, मैंने इसे अभी संपादित कर लिया है। मैं हर बार एक नया रेट्रोफिट ऑब्जेक्ट क्यों बना रहा हूं, यह मेरी ओर से एक निरीक्षण है जिस पर मैंने ध्यान नहीं दिया था और मैं इसे ठीक कर दूंगा
 – 
Uday Vig
25 सितंबर 2021, 21:41

1 उत्तर

सबसे बढ़िया उत्तर

आपका प्रवाह एक ही LiveData पर एकाधिक पर्यवेक्षकों को जोड़ रहा है, और इससे आपको दिखाई देने वाली समस्या हो सकती है।

प्रत्येक बटन क्लिक पर आप getData() द्वारा लौटाए गए LiveData ऑब्जेक्ट को (फिर से) देख रहे हैं।

अपनी getData विधि को इस प्रकार बदलें:

public LiveData<String> getData() {
    return data;
}

और अपनी लोडडेटा विधि सार्वजनिक करें:

public void loadData(String param1, String param2, String param3, String param4, String param5) {
   ...
}

अपने टुकड़े के onCreateView() में अपने LiveData के लिए एक पर्यवेक्षक जोड़ें:

viewmodelData
    .getData()
    .observe(getViewLifecycleOwner(), new Observer<String>() {
        @Override
        public void onChanged(String s) {
            Log.v("TAG", "onChanged: " + s);

            Gson gson = new Gson();
            JsonObject root = gson.fromJson(s, JsonObject.class);
            
            //parsing response...
        }
    });

यह सुनिश्चित करता है कि आपका LiveData केवल एक पर्यवेक्षक द्वारा देखा और नियंत्रित किया जाता है।

बटन क्लिक करने पर कॉल करें:

viewmodelData.loadData("param1", "param2", "param3", "param4", "param5");
0
gioravered 28 सितंबर 2021, 23:35
एक अतिरिक्त के रूप में (इस मुद्दे से असंबंधित) मैं GsonConverterFactory का उपयोग करने की अनुशंसा करता हूं और प्रत्येक प्रतिक्रिया के लिए gson.fromJson() का उपयोग करने के बजाय आपके डेटा को OkHttp द्वारा पार्स किया गया है।
 – 
gioravered
25 सितंबर 2021, 22:05
धन्यवाद, जरूर करेंगे। इसने मेरे लिए काम किया इसलिए बहुत बहुत धन्यवाद। मैंने आपका उत्तर स्वीकार कर लिया है और मैं निश्चित रूप से आपके सुझाव का उपयोग करूंगा। क्या आप मुझे बता सकते हैं कि आप gson.fromJson() का उपयोग करने के बजाय GsonConvertorFactory का उपयोग करने का सुझाव क्यों देते हैं?
 – 
Uday Vig
26 सितंबर 2021, 19:41
ज़रूर। सबसे पहले, इसके लिए केवल एक Gson ऑब्जेक्ट की आवश्यकता होती है। लेकिन बेहतर बात यह है कि OkHttp आपके कॉलबैक को आपके द्वारा पास किए जाने वाले प्रकार के अनुसार आपकी प्रतिक्रियाओं को JSON में "मुफ्त में" बदल देगा। कोड और प्रयास बचाता है और साथ ही आपके द्वारा JSON को पार्स करने के तरीके को केंद्रीकृत करता है। उम्मीद है की वो मदद करदे।
 – 
gioravered
27 सितंबर 2021, 01:38
ज़रूर, बदल देंगे। हर बार पार्स करना थोड़ा दर्द होता है। एक बार फिर धन्यवाद।
 – 
Uday Vig
27 सितंबर 2021, 11:22