পটভূমি পরিষেবা এবং আপডেট ইউআই থেকে ভিউমোডেলের লাইভ ডেটা কীভাবে আপডেট করবেন


97

সম্প্রতি আমি অ্যান্ড্রয়েড আর্কিটেকচারটি অন্বেষণ করছি, এটি গুগল সম্প্রতি চালু করেছে। ডকুমেন্টেশন থেকে আমি এটি খুঁজে পেয়েছি:

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<Users>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // do async operation to fetch users
    }
}

ক্রিয়াকলাপ নীচের হিসাবে এই তালিকাটি অ্যাক্সেস করতে পারে:

public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getUsers().observe(this, users -> {
            // update UI
        });
    }
}

আমার প্রশ্ন হ'ল, আমি এটি করতে যাচ্ছি:

  1. মধ্যে loadUsers()ফাংশন আমি কোথায় আমি প্রথম যে ডেটার জন্য ডেটাবেস (রুম) চেক করবে অ্যাসিঙ্ক্রোনাস ডেটা আনার করছি

  2. আমি যদি সেখানে ডেটা না পাই তবে আমি ওয়েব সার্ভার থেকে ডেটা আনার জন্য একটি এপিআই কল করব।

  3. আমি প্রাপ্ত তথ্যটি ডাটাবেসে (ঘর) সন্নিবেশ করব এবং তথ্য অনুসারে ইউআই আপডেট করব।

এটি করার জন্য প্রস্তাবিত পদ্ধতির কী?

যদি আমি পদ্ধতি Serviceথেকে এপিআই কল করতে একটি শুরু করি তবে আমি loadUsers()কীভাবে সেই MutableLiveData<List<User>> usersথেকে চলকটি আপডেট করতে পারি Service?


9
প্রথমত, আপনি একটি ভাণ্ডার মিস করছেন। আপনার ভিউমোডেল কোনও ডেটা লোড করার কাজ করা উচিত নয়। এগুলি ছাড়াও, আপনার ঘরটি ব্যবহার করার পরে, আপনার পরিষেবায় সরাসরি ভিউমোডলে লাইভ ডেটা আপডেট করার দরকার নেই। পরিষেবাটি কেবলমাত্র রুমে ডেটা tingোকানো হতে পারে, যখন আপনার ভিউমোডেলডেটা কেবলমাত্র রুমের সাথে সংযুক্ত করা উচিত, এবং রুম থেকে আপডেট পাওয়া উচিত (পরিষেবা সন্নিবেশের ডেটার পরে)। তবে নিখুঁত সেরা আর্কিটেকচারের জন্য, এই পৃষ্ঠার নীচে থেকে নেটওয়ার্কবাউন্ডআর রিসোর্স শ্রেণীর বাস্তবায়নটি দেখুন: বিকাশকারী
অ্যান্ড্রয়েড / টপিক / লাইব্রিজি / অর্কিটেকচার / গুইড এইচটিএমএল

এই পরামর্শের জন্য আপনাকে ধন্যবাদ :)
কোডক্যামিও

4
আরওএম বা অ্যান্ড্রয়েড আর্কিটেকচার উপাদানগুলি বর্ণনা করে এমন অফসিয়াল ডক্সে রিপোসিটর শ্রেণীর উল্লেখ নেই
জোনাথন

4
কোড বিভাজন এবং আর্কিটেকচারের জন্য রিপোজিটরি একটি প্রস্তাবিত সেরা অনুশীলন, এই উদাহরণটি দেখুন: কোডলাবস.ডিভেলফার্স জিও
কোডেলেবস

4
ফাংশনটি loadUsers()মূলত ব্যবহারকারীর তথ্য পেতে
রেপোকে

উত্তর:


97

আমি ধরে নিচ্ছি যে আপনি অ্যান্ড্রয়েড আর্কিটেকচার উপাদান ব্যবহার করছেন । আসলে আপনি service, asynctask or handlerডেটা আপডেট করার জন্য যেখানেই ফোন করছেন তাতে কিছু আসে যায় না । আপনি পরিষেবাটি থেকে বা postValue(..)পদ্ধতি ব্যবহার করে অ্যাসিনটাস্ক থেকে ডেটা sertোকাতে পারেন । আপনার ক্লাসটি দেখতে এই রকম হবে:

private void loadUsers() {
    // do async operation to fetch users and use postValue() method
    users.postValue(listOfData)
}

যেমনটি usersহ'ল LiveData, Roomডাটাবেস যেখানেই .োকানো হয়েছে সেখানে ব্যবহারকারীদের ডেটা সরবরাহ করার জন্য দায়বদ্ধ।

Note: আর্কিটেকচারের মতো এমভিভিএম-এ, সংগ্রহস্থল স্থানীয় তথ্য এবং দূরবর্তী ডেটা পরীক্ষা এবং টানার জন্য বেশিরভাগ দায়বদ্ধ।


4
আমি "java.lang.IllegalStateException" পেয়ে যাচ্ছি: মূল থ্রেডে ডাটাবেস অ্যাক্সেস করা যায় না যেহেতু "উপরের মতো আমার ডিবি পদ্ধতিতে কল করার পরে, আপনি কী বলতে পারেন ভুল হতে পারে?
প্রশান্ত

আমি ইউভারে থাকাকালীন আমি ইভারনোট-জব ব্যবহার করছি যা ব্যাকগ্রাউন্ডে ডাটাবেস আপডেট করছে। তবে LiveDataআপডেট হচ্ছে না
অক্ষয় চর্ডিয়া

users.postValue(mUsers);-> তবে, মিউটেবল লাইভডাটা'র পোস্টভ্যালু পদ্ধতিটি কি লাইভ ডেটা গ্রহণ করতে সক্ষম ???
চেওক ইয়ান চেং

4
আমার ভুল valueপরিবর্তে ব্যবহার করা হয়েছিল postValue। আপনার উত্তরের জন্য ধন্যবাদ.
হেসাম

4
@pcj আপনার হয় হয় একটি থ্রেডে রুম অপারেশন করতে হবে বা মূল থ্রেডে অপারেশন সক্ষম করতে হবে - আরও উত্তরের জন্য গুগল।
কিলোকাহন

46

আপনি MutableLiveData<T>.postValue(T value)পটভূমি থ্রেড থেকে পদ্ধতি ব্যবহার করতে পারেন ।

private void loadUsers() {
    // do async operation to fetch users and use postValue() method
   users.postValue(listOfData)
}

19
মনে করিয়ে দেওয়ার জন্য, পোস্টভ্যালু () লাইভডাটাতে সুরক্ষিত তবে মিউটেবল লাইভডেটা
লং রেঞ্জারে

এই কাজটি এমনকি একটি পটভূমি টাস্ক থেকেও এবং এমন পরিস্থিতিতে যেখানে .setValue()অনুমতি দেওয়া হবে না
ডেভজোম

18

... লোডউজার্স () ফাংশনে আমি সংশ্লেষজনকভাবে ডেটা আনছি ... আমি যদি লোড ব্যবহারকারীদের () পদ্ধতি থেকে API কল করার জন্য কোনও পরিষেবা শুরু করি, তবে আমি কীভাবে সেই পরিষেবা থেকে মিউটেবল লাইভডেটা> ব্যবহারকারীদের পরিবর্তনশীল আপডেট করতে পারি?

যদি অ্যাপ্লিকেশনটি কোনও পটভূমির থ্রেডে ব্যবহারকারী ডেটা আনছে তবে পোস্টভ্যালু ( সেটভ্যালুয়ের চেয়ে ) দরকারী হবে।

লোডডাটা পদ্ধতিতে মিউটেবল লাইভডেটা "ব্যবহারকারী" অবজেক্টের একটি উল্লেখ রয়েছে। লোডডাটা পদ্ধতিটি কোথাও থেকে কিছু নতুন ব্যবহারকারীর ডেটা নিয়ে আসে (উদাহরণস্বরূপ, একটি সংগ্রহশালা)।

এখন, যদি এক্সিকিউশনটি একটি পটভূমির থ্রেডে থাকে তবে মিউটেবল লাইভডেটা.পোস্টভ্যালু () মিউটেবল লাইভডেটা ডেটা অবজেক্টের বাইরের পর্যবেক্ষকদের আপডেট করে।

এরকম কিছু হতে পারে:

private MutableLiveData<List<User>> users;

.
.
.

private void loadUsers() {
    // do async operation to fetch users
    ExecutorService service =  Executors.newSingleThreadExecutor();
    service.submit(new Runnable() {
        @Override
        public void run() {
            // on background thread, obtain a fresh list of users
            List<String> freshUserList = aRepositorySomewhere.getUsers();

            // now that you have the fresh user data in freshUserList, 
            // make it available to outside observers of the "users" 
            // MutableLiveData object
            users.postValue(freshUserList);        
        }
    });

}

রিপোজিটরির getUsers()পদ্ধতিটি এমন ডেটাগুলির জন্য একটি এপি কল করতে পারে যা অ্যাসিঙ্ক হয় (এটির জন্য কোনও পরিষেবা শুরু করতে পারে বা অ্যাসিঙ্কটাস্ক হতে পারে) সে ক্ষেত্রে এটি কীভাবে তার রিটার্নের বিবৃতি থেকে তালিকাটি ফেরত দিতে পারে?
কোডক্যামিও

সম্ভবত এটি আর্গুমেন্ট হিসাবে লাইভ ডেটা অবজেক্টকে নিতে পারে। (Repository.getUser (ব্যবহারকারী) এর মতো কিছু)। তারপরে সংগ্রহস্থল পদ্ধতিটি ব্যবহারকারীদের কল করে p পোষ্টভ্যালু নিজেই। এবং, সেই ক্ষেত্রে, লোড ব্যবহারকারীদের এমনকি পটভূমির থ্রেডের প্রয়োজন হয় না।
অ্যালবার্ট সি ব্রাউন

4
উত্তরের জন্য আপনাকে ধন্যবাদ .... তবে আমি স্টোরেজের জন্য একটি রুম ডিবি ব্যবহার করছি এবং ডিএও একটি লাইভ ডেটা <অবজেক্ট> ফেরত দেয় ... আমি কীভাবে লাইভডাটাটিকে কোনও মিউটেবল লাইভডেটাতে রূপান্তর করব <অবজেক্ট>?
কিলোকাহন

আমি মনে করি না রুমের ডিএও সত্যই মিউটেবল লাইভডেটা বিষয়বস্তু নিয়ে কাজ করার উদ্দেশ্যে to ডিএও আপনাকে অন্তর্নিহিত ডিবিতে পরিবর্তনের বিষয়ে অবহিত করছে, তবে, আপনি যদি ডিবিতে মান পরিবর্তন করতে চান, আপনি ডিএওর পদ্ধতিগুলি কল করবেন। এছাড়াও সম্ভবত এখানে আলোচনাটি দরকারী: স্ট্যাকওভারফ্লো.com
অ্যালবার্ট সি ব্রান

3

কটাক্ষপাত অ্যান্ড্রয়েড আর্কিটেকচার নির্দেশিকা যে মত নতুন স্থাপত্য মডিউল সাথে LiveDataএবং ViewModel। তারা এই সঠিক বিষয়টি গভীরতার সাথে আলোচনা করে।

তাদের উদাহরণগুলিতে তারা এটিকে কোনও পরিষেবাতে রাখে না। তারা কীভাবে একটি "সংগ্রহস্থল" মডিউল এবং রেট্রোফিট ব্যবহার করে এটি সমাধান করে তা একবার দেখুন। নীচে অবস্থিত সংযোজনগুলির মধ্যে নেটওয়ার্ক স্টেটের যোগাযোগ, ত্রুটির প্রতিবেদন করা ইত্যাদি সহ আরও সম্পূর্ণ উদাহরণ অন্তর্ভুক্ত রয়েছে include


2

আপনি যদি আপনার এপিকে কল করে থাকেন তবে,

ইন সংগ্রহস্থলের প্রয়োগ :

public MutableLiveData<LoginResponseModel> checkLogin(LoginRequestModel loginRequestModel) {
    final MutableLiveData<LoginResponseModel> data = new MutableLiveData<>();
    apiService.checkLogin(loginRequestModel)
            .enqueue(new Callback<LoginResponseModel>() {
                @Override
                public void onResponse(@NonNull Call<LoginResponseModel> call, @Nullable Response<LoginResponseModel> response) {
                    if (response != null && response.isSuccessful()) {
                        data.postValue(response.body());
                        Log.i("Response ", response.body().getMessage());
                    }
                }

                @Override
                public void onFailure(@NonNull Call<LoginResponseModel> call, Throwable t) {
                    data.postValue(null);
                }
            });
    return data;
}

ইন ViewModel

public LiveData<LoginResponseModel> getUser() {
    loginResponseModelMutableLiveData = repository.checkLogin(loginRequestModel);
    return loginResponseModelMutableLiveData;
}

ইন ভ্রমণ / অসম্পূর্ণ অংশ

loginViewModel.getUser().observe(LoginActivity.this, loginResponseModel -> {
        if (loginResponseModel != null) {
            Toast.makeText(LoginActivity.this, loginResponseModel.getUser().getType(), Toast.LENGTH_SHORT).show();
        }
    });

দ্রষ্টব্য: এখানে JAVTube.8 ল্যাম্বদা ব্যবহার করে আপনি এটি ছাড়া ব্যবহার করতে পারেন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.