نظرة عامة على LiveData جزء من Android Jetpack.

LiveData هي فئة لأصحاب بيانات يمكن ملاحظتها. على عكس أي ملاحظة عادية يمكن ملاحظتها، تعتمد LiveData على مراحل النشاط، أي أنها تحترم دورة حياة مكوّنات التطبيق الأخرى، مثل الأنشطة أو الأجزاء أو الخدمات. يضمن هذا الوعي أن يتم تحديث LiveData فقط لمراقبي مكونات التطبيقات الذين يتصفحون دورة حياة نشطة.

تعتبر البيانات المباشرة المراقب، الذي تمثّله الفئة Observer، في حالة نشطة إذا كانت مراحل نشاطه ضمن الحالة STARTED أو RESUMED. لا تبلّغ LiveData سوى المُراقبين النشطين بالتحديثات. ولا يتم إشعار المستخدمين غير النشطين المسجّلين لمشاهدة عناصر LiveData بالتغييرات.

يمكنك تسجيل مراقِب مقترن بكائن ينفّذ واجهة LifecycleOwner. تسمح هذه العلاقة بإزالة المراقب عند تغيير حالة عنصر Lifecycle المقابل إلى DESTROYED. ويكون ذلك مفيدًا على وجه التحديد للأنشطة والأجزاء لأنّها تستطيع رصد عناصر LiveData بأمان وعدم القلق بشأن تسرُّبها، حيث يتم على الفور إلغاء اشتراك الأنشطة والأجزاء عند تدمير مراحل نشاطها.

لمزيد من المعلومات حول كيفية استخدام LiveData، راجع استخدام كائنات LiveData.

مزايا استخدام البيانات المباشرة

يوفر استخدام البيانات المباشرة المزايا التالية:

التأكد من تطابق واجهة المستخدم مع حالة بياناتك
تتّبع LiveData نمط المراقب. ترسِل ميزة LiveData إشعارات إلى عناصر Observer عند تعديل البيانات الأساسية. يمكنك دمج الرموز البرمجية لتحديث واجهة المستخدم في عناصر Observer هذه. بهذه الطريقة، لن تحتاج إلى تعديل واجهة المستخدم في كل مرة تتغير فيها بيانات التطبيق لأنّ المراقب يجري ذلك نيابةً عنك.
عدم تسرُّب الذاكرة
يتقيّد المراقبون بأغراض Lifecycle وينظفونها بعد تدمير مراحل نشاطها المرتبطة بها.
ما مِن أعطال بسبب الأنشطة المتوقفة
إذا كانت دورة حياة المراقب غير نشطة، كما هو الحال في حالة نشاط ما في الحزمة الخلفية، لن يتلقّى أي أحداث LiveData.
لم تعد هناك حاجة إلى المعالجة اليدوية لمراحل النشاط
تراقب مكونات واجهة المستخدم البيانات ذات الصلة ولا تتوقف عن الملاحظة أو تستأنفها. وتدير ميزة LiveData كل هذا تلقائيًا لأنّها تدرك تغييرات حالة مراحل النشاط ذات الصلة أثناء الملاحظة.
البيانات المحدّثة دائمًا
إذا أصبحت إحدى مراحل النشاط غير نشطة، فإنها تتلقى أحدث البيانات عند تنشيطها مجددًا. على سبيل المثال، يتلقى نشاط كان في الخلفية أحدث البيانات مباشرةً بعد عودته إلى المقدمة.
التغييرات الصحيحة على الإعدادات
في حال إعادة إنشاء نشاط أو جزء بسبب تغيير في الإعدادات، مثل تدوير الجهاز، سيتم على الفور إرسال أحدث البيانات المتاحة.
مشاركة المراجع
يمكنك تمديد عنصر LiveData باستخدام نمط "سينغلتون" لالتفاف خدمات النظام بحيث يمكن مشاركتها في تطبيقك. ويتم ربط الكائن LiveData بخدمة النظام مرة واحدة، وسيتمكّن أي مراقب يحتاج إلى المورد من مشاهدة الكائن LiveData فقط. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة Extend LiveData.

العمل باستخدام كائنات LiveData

اتّبِع الخطوات التالية للتعامل مع عناصر LiveData:

  1. يمكنك إنشاء مثيل LiveData للاحتفاظ بنوع معيّن من البيانات. يتم ذلك عادةً في صف ViewModel.
  2. أنشئ كائن Observer يحدِّد طريقة onChanged() التي تتحكّم في ما يحدث عند تغيُّر البيانات المحجوزة في عنصر LiveData. يمكنك عادةً إنشاء كائن Observer في وحدة التحكّم في واجهة المستخدم، مثل نشاط أو جزء.
  3. أرفِق الكائن Observer بالكائن LiveData باستخدام الطريقة observe(). تستخدم الطريقة observe() كائن LifecycleOwner. يؤدي ذلك إلى اشتراك الكائن Observer في الكائن LiveData حتى يتم إعلامك بالتغييرات. يتم عادةً إرفاق الكائن Observer في وحدة تحكّم واجهة المستخدم، مثل نشاط أو جزء.

عند تعديل القيمة المخزّنة في الكائن LiveData، يتم تشغيل جميع المراقبين المسجَّلين ما دامت قيمة LifecycleOwner المرفقة في الحالة النشطة.

تتيح LiveData للمراقبين المشاركين في وحدات التحكم في واجهة المستخدم الاشتراك في التحديثات. وعندما تتغير البيانات التي يحتفظ بها الكائن LiveData، يتم تحديث واجهة المستخدم تلقائيًا استجابةً لذلك.

إنشاء كائنات LiveData

LiveData هو برنامج تضمين يمكن استخدامه مع أي بيانات، بما في ذلك الكائنات التي تطبّق Collections، مثل List. يتم عادةً تخزين عنصر LiveData في كائن ViewModel ويتم الوصول إليه باستخدام طريقة getter، كما هو موضّح في المثال التالي:

Kotlin

class NameViewModel : ViewModel() {

    // Create a LiveData with a String
    val currentName: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

    // Rest of the ViewModel...
}

Java

public class NameViewModel extends ViewModel {

// Create a LiveData with a String
private MutableLiveData<String> currentName;

    public MutableLiveData<String> getCurrentName() {
        if (currentName == null) {
            currentName = new MutableLiveData<String>();
        }
        return currentName;
    }

// Rest of the ViewModel...
}

في البداية، لا يتم ضبط البيانات في العنصر LiveData.

يمكنك الاطّلاع على مزيد من المعلومات حول مزايا الفئة ViewModel واستخدامها في دليل ViewModel.

مراقبة كائنات LiveData

في معظم الحالات، تكون طريقة onCreate() لمكوِّن التطبيق هي المكان الصحيح لبدء مراقبة عنصر LiveData للأسباب التالية:

  • لضمان عدم إجراء النظام لاستدعاءات مكرّرة من خلال نشاط أو طريقة onResume() في أحد الأجزاء.
  • التأكد من احتواء النشاط أو الجزء على بيانات يمكن عرضها فور تنشيطها. عندما يكون أحد مكونات التطبيق في حالة STARTED، يتلقّى أحدث قيمة من كائنات LiveData التي يرصدها. ويحدث ذلك فقط في حال ضبط العنصر LiveData المطلوب ملاحظته.

بشكل عام، لا تعرض LiveData التحديثات إلا عند تغيُّر البيانات، ولأجهزة الرصد النشطة فقط. استثناء من هذا السلوك هو أن المراقبين يتلقون أيضًا تحديثًا عندما يتغيرون من حالة غير نشطة إلى حالة نشطة. علاوة على ذلك، إذا تغيّر المراقب من غير نشط إلى نشط للمرة الثانية، فلن يتلقى تحديثًا إلا إذا تغيرت القيمة منذ آخر مرة أصبحت فيها نشطة.

ويوضّح الرمز النموذجي التالي كيفية بدء مراقبة كائن LiveData:

Kotlin

class NameActivity : AppCompatActivity() {

    // Use the 'by viewModels()' Kotlin property delegate
    // from the activity-ktx artifact
    private val model: NameViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Other code to setup the activity...

        // Create the observer which updates the UI.
        val nameObserver = Observer<String> { newName ->
            // Update the UI, in this case, a TextView.
            nameTextView.text = newName
        }

        // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
        model.currentName.observe(this, nameObserver)
    }
}

Java

public class NameActivity extends AppCompatActivity {

    private NameViewModel model;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Other code to setup the activity...

        // Get the ViewModel.
        model = new ViewModelProvider(this).get(NameViewModel.class);

        // Create the observer which updates the UI.
        final Observer<String> nameObserver = new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String newName) {
                // Update the UI, in this case, a TextView.
                nameTextView.setText(newName);
            }
        };

        // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
        model.getCurrentName().observe(this, nameObserver);
    }
}

بعد استدعاء observe() مع تمرير nameObserver كمَعلمة، يتم استدعاء onChanged() على الفور لتوفير أحدث قيمة مخزّنة في mCurrentName. إذا لم يضبط الكائن LiveData قيمة في mCurrentName، لا يتم استدعاء onChanged().

تعديل كائنات LiveData

لا تحتوي LiveData على أي طرق متاحة للجميع لتحديث البيانات المخزنة. تعرض الفئة MutableLiveData طريقتَي setValue(T) وpostValue(T) بشكل علني، وعليك استخدامهما إذا كنت بحاجة إلى تعديل القيمة المخزّنة في كائن LiveData. عادةً ما يتم استخدام MutableLiveData في ViewModel، وبعد ذلك تعرض ViewModel عناصر LiveData غير قابلة للتغيير للمراقبين فقط.

بعد إعداد علاقة المراقب، يمكنك تعديل قيمة الكائن LiveData، كما يتضح في المثال التالي، والتي تؤدي إلى ظهور جميع المراقبين عندما ينقر المستخدم على الزر:

Kotlin

button.setOnClickListener {
    val anotherName = "John Doe"
    model.currentName.setValue(anotherName)
}

Java

button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        String anotherName = "John Doe";
        model.getCurrentName().setValue(anotherName);
    }
});

يؤدي استدعاء setValue(T) في المثال إلى استدعاء المراقبين لطرق onChanged() بالقيمة John Doe. يعرض المثال الضغط على زر، ولكن قد يتم استدعاء setValue() أو postValue() لتعديل mName لأسباب مختلفة، بما في ذلك الاستجابة لطلب شبكة أو تحميل قاعدة بيانات. وفي جميع الحالات، يؤدي الاستدعاء إلى setValue() أو postValue() إلى ملاحظة واجهة المستخدم وتعديلها.

استخدام "البيانات المباشرة" مع الغرفة

تتوافق مكتبة الاستمرارية في Room مع طلبات البحث القابلة للتتبّع، التي تعرض عناصر LiveData. تتم كتابة الاستعلامات القابلة للملاحظة كجزء من كائن الوصول إلى قاعدة البيانات (DAO).

تنشئ الغرفة كل الرموز اللازمة لتعديل عنصر LiveData عند تعديل قاعدة بيانات. تقوم التعليمة البرمجية التي تم إنشاؤها بتشغيل الاستعلام بشكل غير متزامن على سلسلة محادثات في الخلفية عند الحاجة. هذا النمط مفيد للحفاظ على البيانات المعروضة في واجهة مستخدم متزامنة مع البيانات المخزنة في قاعدة البيانات. يمكنك الاطّلاع على المزيد من المعلومات حول الغرف ووحدات DAO في دليل المكتبة الدائمة في "الغرفة".

استخدام الكوروتينات مع LiveData

تشمل LiveData إتاحة استخدام الكوروتينات في لغة Kotlin. لمزيد من المعلومات، يُرجى الاطّلاع على استخدام الكوروتينات في لغة Kotlin مع مكونات Android الهندسية.

LiveData في بنية التطبيق

تراعي LiveData مراحل النشاط، وهي تتتبّع مراحل نشاط الكيانات، مثل الأنشطة والأجزاء. يمكنك استخدام LiveData للتواصل بين مالكي دورات الحياة هؤلاء والكائنات الأخرى التي لها عمر مختلف، مثل كائنات ViewModel. تتمثّل المسؤولية الرئيسية لـ ViewModel في تحميل البيانات المتعلّقة بواجهة المستخدم وإدارتها، ما يجعلها مرشحة رائعة للاحتفاظ بكائنات LiveData. يمكنك إنشاء كائنات LiveData في ViewModel واستخدامها لكشف الحالة لطبقة واجهة المستخدم.

يجب ألا تتضمّن الأنشطة والأجزاء مثيلات LiveData لأن دورها هو عرض البيانات وليس حالة الاحتفاظ بالبيانات. أيضًا، يؤدي الحفاظ على الأنشطة والأجزاء خالية من الاحتفاظ بالبيانات إلى تسهيل كتابة اختبارات الوحدات.

قد يكون من المغري استخدام كائنات LiveData في فئة طبقة البيانات، إلا أنّ LiveDataليس مصمّمًا لمعالجة عمليات البث غير المتزامنة للبيانات. على الرغم من أنّه يمكنك استخدام عمليات تحويل LiveData وMediatorLiveData لتحقيق ذلك، هناك عيوب في هذا الأسلوب: إمكانية دمج مصادر البيانات محدودة للغاية، وتتم ملاحظة جميع كائنات LiveData (بما في ذلك العناصر التي تم إنشاؤها من خلال عمليات التحويل) في سلسلة التعليمات الرئيسية. الرمز البرمجي أدناه هو مثال على كيف يمكن أن يؤدي الاحتفاظ بـ LiveData في Repository إلى حظر سلسلة التعليمات الرئيسية:

Kotlin

class UserRepository {

    // DON'T DO THIS! LiveData objects should not live in the repository.
    fun getUsers(): LiveData<List<User>> {
        ...
    }

    fun getNewPremiumUsers(): LiveData<List<User>> {
        return getUsers().map { users ->
            // This is an expensive call being made on the main thread and may
            // cause noticeable jank in the UI!
            users
                .filter { user ->
                  user.isPremium
                }
          .filter { user ->
              val lastSyncedTime = dao.getLastSyncedTime()
              user.timeCreated > lastSyncedTime
                }
    }
}

Java

class UserRepository {

    // DON'T DO THIS! LiveData objects should not live in the repository.
    LiveData<List<User>> getUsers() {
        ...
    }

    LiveData<List<User>> getNewPremiumUsers() {
    return Transformations.map(getUsers(),
        // This is an expensive call being made on the main thread and may cause
        // noticeable jank in the UI!
        users -> users.stream()
            .filter(User::isPremium)
            .filter(user ->
                user.getTimeCreated() > dao.getLastSyncedTime())
            .collect(Collectors.toList()));
    }
}

إذا كنت بحاجة إلى استخدام مصادر البيانات في طبقات أخرى من تطبيقك، ننصحك باستخدام تدفقات Kotlin، ثم تحويلها إلى LiveData في ViewModel باستخدام asLiveData(). يمكنك الاطّلاع على مزيد من المعلومات حول استخدام لغة Flow في Kotlin مع LiveData في هذا الدرس التطبيقي حول الترميز. بالنسبة إلى قواعد الترميز التي تم إنشاؤها باستخدام لغة Java، يمكنك استخدام أداة Executors إلى جانب عمليات معاودة الاتصال أو RxJava.

توسيع LiveData

تعتبر البيانات المباشرة المراقب في حالة نشطة إذا كانت دورة حياة المراقب إما في حالتي STARTED أو RESUMED. يوضّح الرمز النموذجي التالي كيفية توسيع فئة LiveData:

Kotlin

class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
    private val stockManager = StockManager(symbol)

    private val listener = { price: BigDecimal ->
        value = price
    }

    override fun onActive() {
        stockManager.requestPriceUpdates(listener)
    }

    override fun onInactive() {
        stockManager.removeUpdates(listener)
    }
}

Java

public class StockLiveData extends LiveData<BigDecimal> {
    private StockManager stockManager;

    private SimplePriceListener listener = new SimplePriceListener() {
        @Override
        public void onPriceChanged(BigDecimal price) {
            setValue(price);
        }
    };

    public StockLiveData(String symbol) {
        stockManager = new StockManager(symbol);
    }

    @Override
    protected void onActive() {
        stockManager.requestPriceUpdates(listener);
    }

    @Override
    protected void onInactive() {
        stockManager.removeUpdates(listener);
    }
}

يتضمن تنفيذ أداة معالجة السعر في هذا المثال الطرق المهمة التالية:

  • يتم استدعاء الطريقة onActive() عندما يكون للكائن LiveData مراقب نشط. هذا يعني أنك بحاجة إلى البدء في مراقبة تحديثات أسعار الأسهم من هذه الطريقة.
  • يتم استدعاء الطريقة onInactive() عندما لا يكون للكائن LiveData أي مراقبين نشطين. ما مِن سبب للبقاء على اتصال بخدمة StockManager لأنّه لا يوجد مراقبون يستمعون إليك.
  • تعدِّل الطريقة setValue(T) قيمة المثيل LiveData وتُبلغ أي ملاحظين نشطين بالتغيير.

يمكنك استخدام الصف "StockLiveData" على النحو التالي:

Kotlin

public class MyFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val myPriceListener: LiveData<BigDecimal> = ...
        myPriceListener.observe(viewLifecycleOwner, Observer<BigDecimal> { price: BigDecimal? ->
            // Update the UI.
        })
    }
}

Java

public class MyFragment extends Fragment {
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        LiveData<BigDecimal> myPriceListener = ...;
        myPriceListener.observe(getViewLifecycleOwner(), price -> {
            // Update the UI.
        });
    }
}

تمرّر الطريقة observe() دالة LifecycleOwner المرتبطة بعرض الجزء على أنّها الوسيطة الأولى. يشير ذلك إلى أنّ هذا المراقب مرتبط بالكائن Lifecycle المرتبط بالمالك، ما يعني:

  • إذا لم يكن الكائن Lifecycle في حالة نشطة، لن يتم استدعاء المراقب حتى إذا تغيّرت القيمة.
  • بعد تدمير الكائن Lifecycle، تتم إزالة المراقب تلقائيًا.

وإدراكًا لمراحل النشاط في عناصر LiveData، يمكن مشاركتها بين عدة أنشطة وأجزاء وخدمات. لإبقاء المثال بسيطًا، يمكنك تنفيذ الفئة LiveData كعملية مفردة على النحو التالي:

Kotlin

class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
    private val stockManager: StockManager = StockManager(symbol)

    private val listener = { price: BigDecimal ->
        value = price
    }

    override fun onActive() {
        stockManager.requestPriceUpdates(listener)
    }

    override fun onInactive() {
        stockManager.removeUpdates(listener)
    }

    companion object {
        private lateinit var sInstance: StockLiveData

        @MainThread
        fun get(symbol: String): StockLiveData {
            sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol)
            return sInstance
        }
    }
}

Java

public class StockLiveData extends LiveData<BigDecimal> {
    private static StockLiveData sInstance;
    private StockManager stockManager;

    private SimplePriceListener listener = new SimplePriceListener() {
        @Override
        public void onPriceChanged(BigDecimal price) {
            setValue(price);
        }
    };

    @MainThread
    public static StockLiveData get(String symbol) {
        if (sInstance == null) {
            sInstance = new StockLiveData(symbol);
        }
        return sInstance;
    }

    private StockLiveData(String symbol) {
        stockManager = new StockManager(symbol);
    }

    @Override
    protected void onActive() {
        stockManager.requestPriceUpdates(listener);
    }

    @Override
    protected void onInactive() {
        stockManager.removeUpdates(listener);
    }
}

يمكنك استخدام هذه الطريقة في الجزء على النحو التالي:

Kotlin

class MyFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        StockLiveData.get(symbol).observe(viewLifecycleOwner, Observer<BigDecimal> { price: BigDecimal? ->
            // Update the UI.
        })

    }

Java

public class MyFragment extends Fragment {
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        StockLiveData.get(symbol).observe(getViewLifecycleOwner(), price -> {
            // Update the UI.
        });
    }
}

يمكن أن ترصد الأجزاء والأنشطة المتعددة مثيل MyPriceListener. لا يتم ربط LiveData بخدمة النظام إلا إذا كانت خدمة واحدة أو أكثر منها مرئية ونشطة.

تحويل البيانات المباشرة

ننصحك بإجراء تغييرات على القيمة المخزّنة في كائن LiveData قبل إرساله إلى المراقبين، أو قد تحتاج إلى عرض مثيل LiveData مختلف استنادًا إلى قيمة مثيل آخر. توفِّر حزمة Lifecycle فئة Transformations التي تتضمّن طرقًا مساعِدة تتوافق مع هذه السيناريوهات.

Transformations.map()
يطبِّق هذا العنصر دالة على القيمة المخزّنة في الكائن LiveData، وينشر النتيجة النهائية.

Kotlin

val userLiveData: LiveData<User> = UserLiveData()
val userName: LiveData<String> = userLiveData.map {
    user -> "${user.name} ${user.lastName}"
}

Java

LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
    user.name + " " + user.lastName
});
Transformations.switchMap()
على غرار map()، يتم تطبيق دالة على القيمة المخزَّنة في الكائن LiveData ثم فك التفاف النتيجة ونقلها إلى مصدر البيانات. يجب أن تعرض الدالة التي يتم تمريرها إلى switchMap() كائن LiveData، على النحو الموضّح في المثال التالي:

Kotlin

private fun getUser(id: String): LiveData<User> {
  ...
}
val userId: LiveData<String> = ...
val user = userId.switchMap { id -> getUser(id) }

Java

private LiveData<User> getUser(String id) {
  ...;
}

LiveData<String> userId = ...;
LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );

يمكنك استخدام طرق التحويل لنقل المعلومات خلال دورة حياة المراقب. لا يتم احتساب التحويلات إلا إذا كان المراقب يشاهد عنصر LiveData المعروض. ونظرًا لإجراء عمليات التحويل ببطء، يتم تمرير السلوك المرتبط بدورة الحياة ضمنيًا بدون الحاجة إلى استدعاءات أو تبعيات إضافية صريحة.

إذا كنت تعتقد أنّك بحاجة إلى عنصر Lifecycle داخل كائن ViewModel، قد يكون التحويل حلاً أفضل. على سبيل المثال، لنفترض أنّ لديك عنصر واجهة مستخدم يقبل العنوان ويعرض الرمز البريدي لهذا العنوان. يمكنك تطبيق علامة ViewModel البسيطة لهذا المكوِّن كما هو موضّح في الرمز النموذجي التالي:

Kotlin

class MyViewModel(private val repository: PostalCodeRepository) : ViewModel() {

    private fun getPostalCode(address: String): LiveData<String> {
        // DON'T DO THIS
        return repository.getPostCode(address)
    }
}

Java

class MyViewModel extends ViewModel {
    private final PostalCodeRepository repository;
    public MyViewModel(PostalCodeRepository repository) {
       this.repository = repository;
    }

    private LiveData<String> getPostalCode(String address) {
       // DON'T DO THIS
       return repository.getPostCode(address);
    }
}

يحتاج مكوّن واجهة المستخدم بعد ذلك إلى إلغاء التسجيل من كائن LiveData السابق والتسجيل في المثيل الجديد في كل مرة يتم فيها استدعاء getPostalCode(). علاوةً على ذلك، إذا تمت إعادة إنشاء مكوّن واجهة المستخدم، سيتم إجراء طلب آخر لطريقة repository.getPostCode() بدلاً من استخدام نتيجة الاستدعاء السابق.

بدلاً من ذلك، يمكنك تنفيذ البحث عن الرمز البريدي كتحويل لإدخال العنوان، كما هو موضّح في المثال التالي:

Kotlin

class MyViewModel(private val repository: PostalCodeRepository) : ViewModel() {
    private val addressInput = MutableLiveData<String>()
    val postalCode: LiveData<String> = addressInput.switchMap {
            address -> repository.getPostCode(address) }


    private fun setInput(address: String) {
        addressInput.value = address
    }
}

Java

class MyViewModel extends ViewModel {
    private final PostalCodeRepository repository;
    private final MutableLiveData<String> addressInput = new MutableLiveData();
    public final LiveData<String> postalCode =
            Transformations.switchMap(addressInput, (address) -> {
                return repository.getPostCode(address);
             });

  public MyViewModel(PostalCodeRepository repository) {
      this.repository = repository
  }

  private void setInput(String address) {
      addressInput.setValue(address);
  }
}

في هذه الحالة، يتم تعريف الحقل postalCode على أنّه تحويل للسمة addressInput. ما دام تطبيقك يتضمّن مراقبًا نشطًا مرتبطًا بالحقل postalCode، تتم إعادة حساب قيمة الحقل واستردادها كلما تم تغيير addressInput.

تسمح هذه الآلية بمستويات أدنى من التطبيق بإنشاء عناصر LiveData يتم احتسابها بطريقة كسول عند الطلب. يمكن لكائن ViewModel الحصول بسهولة على مراجع لكائنات LiveData ثم تحديد قواعد التحويل فوقها.

إنشاء عمليات تحويل جديدة

هناك الكثير من عمليات التحويل المحددة المختلفة التي قد تكون مفيدة في تطبيقك، لكن لا يتم تقديمها بشكل افتراضي. لتنفيذ التحويل الخاص بك، يمكنك استخدام الفئة MediatorLiveData التي تستمع إلى عناصر LiveData الأخرى وتعالج الأحداث الصادرة عنها. ينشر MediatorLiveData حالته بشكل صحيح في كائن المصدر LiveData. لمعرفة المزيد حول هذا النمط، راجِع المستندات المرجعية للفئة Transformations.

دمج مصادر متعددة LiveData

MediatorLiveData هي فئة فرعية من LiveData تتيح لك دمج مصادر متعددة LiveData. يتم بعد ذلك تشغيل مراقبي كائنات MediatorLiveData كلما تغيّر أي من كائنات مصدر LiveData الأصلية.

على سبيل المثال، إذا كان لديك عنصر LiveData في واجهة المستخدم يمكن تعديله من قاعدة بيانات محلية أو شبكة، يمكنك إضافة المصادر التالية إلى كائن MediatorLiveData:

  • عنصر LiveData مرتبط بالبيانات المخزّنة في قاعدة البيانات.
  • عنصر LiveData مرتبط بالبيانات التي يتم الوصول إليها من الشبكة

يحتاج نشاطك فقط إلى مراقبة الكائن MediatorLiveData لتلقّي آخر الأخبار من كلا المصدرَين. للحصول على مثال مفصّل، يُرجى الاطّلاع على قسم الملحق: عرض حالة الشبكة في دليل بنية التطبيقات.

مراجع إضافية

لمعرفة المزيد من المعلومات حول صف LiveData، يُرجى الرجوع إلى المَراجع التالية.

عيّنات

الدروس التطبيقية حول الترميز

المدوّنات

الفيديوهات الطويلة