نمای کلی LiveData بخشی از Android Jetpack.
LiveData یک کلاس نگهدارنده داده قابلمشاهده است. برخلاف یک قابلمشاهده معمولی، LiveData از چرخه حیات آگاه است،
به این معنی که به چرخه حیات سایر اجزای برنامه، مانند فعالیتها،
قطعات، یا خدمات احترام میگذارد. این آگاهی تضمین میکند که LiveData فقط ناظران مؤلفه برنامه را که در وضعیت چرخه حیات فعال هستند بهروز میکند.
LiveData ناظری را که با کلاس
Observer نشان داده میشود،
درصورتی در حالت فعال درنظر میگیرد که چرخه حیات آن در حالت
STARTED یا
RESUMED
باشد. LiveData فقط ناظران فعال را درباره بهروزرسانیها مطلع میکند. ناظران غیرفعال ثبتشده برای تماشای اشیاء LiveData از تغییرات مطلع نمیشوند.
میتوانید ناظری را که با شیء پیادهسازیکننده میانای
LifecycleOwner
جفت شده است ثبت کنید. این رابطه اجازه میدهد وقتی وضعیت شیء
Lifecycle
مربوطه به
DESTROYED
تغییر میکند، ناظر برداشته شود.
این بهویژه برای فعالیتها و قطعهها مفید است زیرا میتوانند بهطور ایمن
اشیاء LiveData را مشاهده کنند
و نگران نشت نباشند—فعالیتها و قطعهها فوراً
لغو اشتراک میشوند وقتی چرخههای حیات آنها نابود میشود.
برای اطلاعات بیشتر درباره نحوه استفاده از LiveData، به کار با اشیاء LiveData مراجعه کنید.
مزایای استفاده از LiveData
استفاده از LiveData مزایای زیر را بههمراه دارد:
- مطمئن میشود که واسط کاربر با وضعیت دادههای شما مطابقت دارد
- LiveData از الگوی ناظر پیروی میکند. وقتی دادههای اساسی تغییر میکند، LiveData به اشیای
Observerاطلاع میدهد. میتوانید کدتان را برای بهروزرسانی واسط کاربر در اینObserverشیء ادغام کنید. به این ترتیب، نیازی نیست هر بار که دادههای برنامه تغییر میکند، واسط کاربر را بهروز کنید، زیرا ناظر این کار را برای شما انجام میدهد. - بدون نشت حافظه
- ناظران به
Lifecycleشیءها محدود هستند و وقتی چرخه حیات مرتبط با آنها ازبین میرود، خودشان را پاک میکنند. - بدون خرابی بهدلیل فعالیتهای متوقفشده
- اگر چرخه حیات ناظر غیرفعال باشد، مثلاً درمورد فعالیتی در پشته قبلیها، هیچ رویداد LiveData دریافت نمیکند.
- دیگر نیازی به مدیریت دستی چرخه حیات نیست
- مؤلفههای میانای کاربری فقط دادههای مربوطه را مشاهده میکنند و مشاهده را متوقف یا ازسر نمیگیرند. LiveData بهطور خودکار همه این موارد را مدیریت میکند زیرا از تغییرات وضعیت چرخه حیات مربوطه درحین مشاهده آگاه است.
- دادههای همیشه بهروز
- اگر چرخه حیات غیرفعال شود، پساز فعال شدن مجدد، جدیدترین دادهها را دریافت میکند. برای مثال، فعالیتی که در پسزمینه بوده است، بلافاصله پساز بازگشت به پیشزمینه، جدیدترین دادهها را دریافت میکند.
- تغییرات پیکربندی مناسب
- اگر فعالیت یا قطعهای بهدلیل تغییر پیکربندی، مانند چرخش دستگاه، دوباره ایجاد شود، بلافاصله جدیدترین دادههای دردسترس را دریافت میکند.
- منابع همرسانی
- میتوانید شیء
LiveDataرا بااستفاده از الگوی تکقلو گسترش دهید تا خدمات سیستم را دربرگیرد و بتوان آنها را در برنامهتان همرسانی کرد. شیءLiveDataیکبار به خدمات سیستم متصل میشود و سپس هر ناظری که به منبع نیاز داشته باشد میتواند شیءLiveDataرا تماشا کند. برای اطلاعات بیشتر، به گسترش LiveData مراجعه کنید.
کار کردن با اشیاء LiveData
برای کار با اشیاء LiveData، این مراحل را دنبال کنید:
- نمونهای از
LiveDataبرای نگهداری نوع خاصی از دادهها ایجاد کنید. این کار معمولاً در کلاسViewModelانجام میشود. - شیء
Observerایجاد کنید که روشonChanged()را تعریف میکند. این روش کنترل میکند که وقتی دادههای نگهداشتهشده شیءLiveDataتغییر میکند چه اتفاقی میافتد. معمولاً یک شیءObserverرا در یک کنترلکننده میانای کاربر، مانند یک فعالیت یا قطعه، ایجاد میکنید. شیء
Observerرا بااستفاده از روشobserve()به شیءLiveDataپیوست کنید. روشobserve()یک شیءLifecycleOwnerمیگیرد. این کار شیءObserverرا در شیءLiveDataمشترک میکند تا از تغییرات مطلع شود. معمولاً شیءObserverرا در یک کنترلکننده واسط کاربر، مانند فعالیت یا قطعه، پیوست میکنید.
وقتی مقدار ذخیرهشده در شیء LiveData را بهروز میکنید، تا زمانی که LifecycleOwner پیوستشده در حالت فعال باشد، همه ناظران ثبتشده را راهاندازی میکند.
LiveData به ناظران کنترلکننده میانای کاربر اجازه میدهد تا در بهروزرسانیها مشترک شوند. وقتی دادههای
موجود در شیء LiveData تغییر میکند، واسط کاربر بهطور خودکار در پاسخ بهروز میشود.
ایجاد کردن اشیای LiveData
LiveData یک پوشاننده است که میتواند با هر دادهای استفاده شود، ازجمله اشیایی که
Collections را پیادهسازی میکنند، مانند List. شیء LiveData معمولاً در شیء ViewModel ذخیره میشود و ازطریق روش getter قابلدسترسی است، همانطور که در مثال زیر نشان داده شده است:
کاتلین
class NameViewModel : ViewModel() { // Create a LiveData with a String val currentName: MutableLiveData<String> by lazy { MutableLiveData<String>() } // Rest of the ViewModel... }
جاوا
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 را نشان میدهد:
کاتلین
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) } }
جاوا
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 را بهروز کنید، همانطور که در مثال زیر نشان داده شده است، که وقتی کاربر روی دکمهای تکضرب میزند، همه ناظران را فعال میکند:
کاتلین
button.setOnClickListener { val anotherName = "John Doe" model.currentName.setValue(anotherName) }
جاوا
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() ناظران را راهاندازی میکند و
رابط کاربری را بهروز میکند.
استفاده از LiveData با Room
کتابخانه پایداری Room از پُرسمانهای قابلمشاهده پشتیبانی میکند که اشیای LiveData را برمیگردانند.
پُرسمانهای قابلمشاهده بهعنوان بخشی از «شیء دسترسی به پایگاه داده» (DAO) نوشته میشوند.
Room همه کدهای لازم را برای بهروزرسانی شیء LiveData هنگام بهروزرسانی پایگاه داده تولید میکند. کد تولیدشده درصورت نیاز پُرسمان را بهصورت ناهمگام در رشته پسزمینه اجرا میکند. این الگو برای همگام نگه داشتن دادههای نمایشدادهشده در میانای کاربر با دادههای ذخیرهشده در پایگاه داده مفید است. میتوانید اطلاعات بیشتری درباره Room و DAO در راهنمای کتابخانه پایداری Room بخوانید.
استفاده از روالهای مشترک با LiveData
LiveData شامل پشتیبانی از روالهای همزمان Kotlin است. برای اطلاعات بیشتر،
استفاده از روالهای مشترک Kotlin با مؤلفههای معماری Android را ببینید.
LiveData در معماری برنامه
LiveData از چرخه حیات آگاه است و چرخه حیات موجودیتهایی مانند
فعالیتها و قطعهها را دنبال میکند. از LiveData برای برقراری ارتباط بین این مالکان چرخه حیات و اشیای دیگر با طول عمر متفاوت، مانند اشیای ViewModel، استفاده کنید.
مسئولیت اصلی ViewModel بار کردن و مدیریت دادههای مربوط به میانای کاربر است، که آن را به گزینهای عالی برای نگهداری اشیای LiveData تبدیل میکند. اشیاء LiveData را در ViewModel ایجاد کنید و از آنها برای نمایش وضعیت به لایه واسط کاربر استفاده کنید.
فعالیتها و قطعهها نباید نمونههای LiveData را نگه دارند زیرا نقش آنها نمایش دادهها است، نه نگهداری وضعیت. همچنین، آزاد نگه داشتن فعالیتها و قطعهها
از نگهداری دادهها، نوشتن آزمونهای واحد را آسانتر میکند.
ممکن است وسوسه شوید که با اشیاء LiveData در کلاس لایه دادهتان کار کنید، اما
LiveData برای مدیریت جریانهای ناهمگام داده طراحی نشده است. هرچند
میتوانید از تبدیلهای LiveData و MediatorLiveData
برای دستیابی به این هدف استفاده کنید، این رویکرد معایبی دارد: قابلیت ترکیب کردن جریانهای
داده بسیار محدود است و همه اشیای LiveData (ازجمله اشیای ایجادشده
ازطریق تبدیلها) در رشته اصلی مشاهده میشوند. کد زیر نمونهای از این است که چگونه نگهداشتن LiveData در Repository میتواند رشته اصلی را مسدود کند:
کاتلین
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 } } }
جاوا
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 Flows و سپس تبدیل آنها به LiveData در
ViewModel بااستفاده از asLiveData() را مدنظر قرار دهید.
در این codelab درباره استفاده از Kotlin Flow با LiveData بیشتر بدانید.
برای پایگاههای کد ساختهشده با Java، استفاده از Executors
را در ارتباط با فراخوانیهای برگشتی یا RxJava درنظر بگیرید.
گسترش LiveData
LiveData ناظر را درصورتی در حالت فعال درنظر میگیرد که چرخه حیات ناظر در یکی از حالتهای
STARTED
یا RESUMED
باشد. نمونه کد زیر نحوه گسترش کلاس
LiveData را نشان میدهد:
کاتلین
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) } }
جاوا
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); } }
پیادهسازی شنونده قیمت در این مثال شامل روشهای مهم زیر است:
- وقتی شیء
LiveDataناظر فعال داشته باشد، روشonActive()فراخوانی میشود. این یعنی باید شروع به مشاهده بهروزرسانیهای قیمت سهام از این روش کنید. - وقتی شیء
LiveDataهیچ ناظر فعالی نداشته باشد، روشonInactive()فراخوانی میشود. چون هیچ ناظری گوش نمیدهد، دلیلی برای متصل ماندن به سرویسStockManagerوجود ندارد. - روش
setValue(T)مقدار نمونهLiveDataرا بهروز میکند و هرگونه ناظر فعال را از تغییر مطلع میکند.
میتوانید از کلاس StockLiveData بهصورت زیر استفاده کنید:
کاتلین
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. }) } }
جاوا
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 را بهصورت تکقلو بهشرح زیر پیادهسازی کنید:
کاتلین
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 } } }
جاوا
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); } }
و میتوانید از آن در قطعه بهصورت زیر استفاده کنید:
کاتلین
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. }) }
جاوا
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 به ناظران، تغییراتی در مقدار ذخیرهشده در آن ایجاد کنید، یا ممکن است لازم باشد نمونه LiveData متفاوتی را براساس مقدار نمونه دیگری برگردانید. بسته
Lifecycle
کلاس
Transformations
را ارائه میدهد که شامل روشهای کمکی است که از این سناریوها پشتیبانی میکنند.
Transformations.map()- تابعی را روی مقدار ذخیرهشده در شیء
LiveDataاعمال میکند و نتیجه را به پاییندست منتشر میکند.
کاتلین
val userLiveData: LiveData<User> = UserLiveData() val userName: LiveData<String> = userLiveData.map { user -> "${user.name} ${user.lastName}" }
جاوا
LiveData<User> userLiveData = ...; LiveData<String> userName = Transformations.map(userLiveData, user -> { user.name + " " + user.lastName });
Transformations.switchMap()- مشابه
map()، تابعی را بر مقدار ذخیرهشده در شیءLiveDataاعمال میکند و نتیجه را باز میکند و به پاییندست ارسال میکند. تابع ارسالشده بهswitchMap()باید شیءLiveDataرا برگرداند، همانطور که در مثال زیر نشان داده شده است:
کاتلین
private fun getUser(id: String): LiveData<User> { ... } val userId: LiveData<String> = ... val user = userId.switchMap { id -> getUser(id) }
جاوا
private LiveData<User> getUser(String id) { ...; } LiveData<String> userId = ...; LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );
میتوانید از روشهای تبدیل برای انتقال اطلاعات در سراسر چرخه حیات ناظر استفاده کنید. تبدیلها محاسبه نمیشوند مگراینکه ناظری شیء LiveData برگرداندهشده را تماشا کند. چون تبدیلها بهصورت تنبل محاسبه میشوند، رفتار مرتبط با چرخه حیات بهطور ضمنی بدون نیاز به فراخوانیها یا وابستگیهای صریح اضافی منتقل میشود.
اگر فکر میکنید به شیء Lifecycle در داخل شیء
ViewModel نیاز دارید،
احتمالاً تبدیل راهحل بهتری است. برای مثال، فرض کنید مؤلفه واسط کاربریای دارید که نشانی را میپذیرد و کد پستی آن نشانی را برمیگرداند. میتوانید ViewModel ساده را برای این مؤلفه پیادهسازی کنید، همانطور که در کد نمونه زیر نشان داده شده است:
کاتلین
class MyViewModel(private val repository: PostalCodeRepository) : ViewModel() { private fun getPostalCode(address: String): LiveData<String> { // DON'T DO THIS return repository.getPostCode(address) } }
جاوا
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() راهاندازی میکند.
درعوض، میتوانید جستجوی کد پستی را بهعنوان تبدیلی از ورودی نشانی پیادهسازی کنید، همانطور که در مثال زیر نشان داده شده است:
کاتلین
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 } }
جاوا
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، به
منابع زیر مراجعه کنید.
نمونهها
- Sunflower، برنامه نمایشی که روالهای مطلوب را با Architecture Components نشان میدهد
Codelabs
- Android Room with a View (Java) (Kotlin)
- یادگیری روالهای مشترک پیشرفته با Kotlin Flow و LiveData
وبلاگها
- ViewModels and LiveData: Patterns + AntiPatterns
- LiveData beyond the ViewModel — Reactive patterns using Transformations and MediatorLiveData
- LiveData with SnackBar, Navigation and other events (the SingleLiveEvent case)
ویدیوها
توصیهشده برای شما
- توجه: وقتی جاوا اسکریپت خاموش باشد، نوشتار پیوند نمایش داده میشود
- استفاده کردن از روالهای مشترک Kotlin با مؤلفههای آگاه از چرخه حیات
- Handling Lifecycles with Lifecycle-Aware Components
- آزمایش کردن پیادهسازی صفحهبندی