این کد لبه بخشی از دوره آموزشی Android Kotlin Fundamentals است. اگر به ترتیب روی کدها کار کنید، بیشترین ارزش را از این دوره خواهید گرفت. همه کد لبه های دوره در صفحه فرود کد لبه های Android Kotlin Fundamentals فهرست شده اند.
مقدمه
در لبه کد قبلی، از ViewModel در برنامه GuessTheWord استفاده کردید تا به داده های برنامه اجازه دهید از تغییرات پیکربندی دستگاه جان سالم به در ببرند. در این کد لبه یاد می گیرید که چگونه LiveData با داده های کلاس های ViewModel ادغام کنید. LiveData ، که یکی از اجزای معماری اندروید است، به شما امکان می دهد اشیاء داده بسازید که هنگام تغییر پایگاه داده زیربنایی، نماها را مطلع می کنند.
برای استفاده از کلاس LiveData ، "ناظرها" (به عنوان مثال، فعالیت ها یا قطعات) را تنظیم می کنید که تغییرات در داده های برنامه را مشاهده می کنند. LiveData از چرخه حیات آگاه است، بنابراین فقط ناظران مؤلفه برنامه را که در حالت چرخه حیات فعال هستند به روز می کند.
آنچه از قبل باید بدانید
- نحوه ایجاد برنامه های اساسی اندروید در Kotlin.
- چگونه بین مقاصد برنامه خود حرکت کنید.
- فعالیت و چرخه حیات قطعه
- نحوه استفاده از اشیاء
ViewModelدر برنامه - نحوه ایجاد اشیاء
ViewModelبا استفاده از رابطViewModelProvider.Factory.
چیزی که یاد خواهید گرفت
- چه چیزی اشیاء
LiveDataرا مفید می کند. - چگونه
LiveDataبه داده های ذخیره شده درViewModelاضافه کنیم. - زمان و نحوه استفاده از
MutableLiveData. - نحوه اضافه کردن متدهای مشاهدهگر برای مشاهده تغییرات در
LiveData. - نحوه کپسوله کردن
LiveDataبا استفاده از ویژگی پشتیبان. - نحوه برقراری ارتباط بین یک کنترلر UI و
ViewModelمربوطه آن.
کاری که خواهی کرد
- از
LiveDataبرای کلمه و امتیاز در برنامه GuessTheWord استفاده کنید. - ناظرانی را اضافه کنید که متوجه تغییر کلمه یا امتیاز می شوند.
- نماهای متنی را که مقادیر تغییر یافته را نمایش می دهند، به روز کنید.
- از الگوی مشاهده گر
LiveDataبرای اضافه کردن یک رویداد تمام شده بازی استفاده کنید. - دکمه Play Again را اجرا کنید.
در بخش کدهای درس 5، برنامه GuessTheWord را توسعه می دهید که با کد شروع شروع می شود. GuessTheWord یک بازی دو نفره به سبک charades است که در آن بازیکنان برای دستیابی به بالاترین امتیاز ممکن با یکدیگر همکاری می کنند.
بازیکن اول به کلمات موجود در برنامه نگاه می کند و هر کدام را به نوبه خود عمل می کند و مطمئن می شود که کلمه را به بازیکن دوم نشان نمی دهد. بازیکن دوم سعی می کند کلمه را حدس بزند.
برای انجام بازی، اولین بازیکن برنامه را روی دستگاه باز می کند و کلمه ای را می بیند، به عنوان مثال "گیتار"، همانطور که در تصویر زیر نشان داده شده است.
اولین بازیکن کلمه را اجرا می کند و مراقب است که در واقع خود کلمه را نگوید.
- وقتی بازیکن دوم کلمه را به درستی حدس زد، بازیکن اول دکمه Got It را فشار می دهد که تعداد را یک عدد افزایش می دهد و کلمه بعدی را نشان می دهد.
- اگر بازیکن دوم نتواند کلمه را حدس بزند، بازیکن اول دکمه Skip را فشار می دهد که تعداد را یک کاهش می دهد و به کلمه بعدی می رود.
- برای پایان بازی، دکمه پایان بازی را فشار دهید. (این قابلیت در کد شروع برای اولین آزمایشگاه کد در این سری نیست.)
در این لبه کد، برنامه GuessTheWord را با افزودن یک رویداد برای پایان دادن به بازی هنگامی که کاربر در میان تمام کلمات موجود در برنامه چرخش میکند، بهبود میبخشید. شما همچنین یک دکمه Play Again را در قسمت امتیاز اضافه می کنید تا کاربر بتواند بازی را دوباره انجام دهد.
صفحه عنوان |
صفحه نمایش بازی |
صفحه نمایش امتیاز |
در این کار، کد شروع خود را برای این کد لبه پیدا کرده و اجرا می کنید. میتوانید از برنامه GuessTheWord که در Codelab قبلی ساختهاید بهعنوان کد شروع استفاده کنید، یا میتوانید یک برنامه شروع را دانلود کنید.
- (اختیاری) اگر از کد خود از کد آزمایشگاه قبلی استفاده نمی کنید، کد شروع را برای این کد لبه دانلود کنید . کد را از حالت فشرده خارج کرده و پروژه را در Android Studio باز کنید.
- برنامه را اجرا کنید و بازی را انجام دهید.
- توجه داشته باشید که دکمه Skip کلمه بعدی را نمایش می دهد و امتیاز را یک بار کاهش می دهد و دکمه Got It کلمه بعدی را نشان می دهد و امتیاز را یک افزایش می دهد. دکمه پایان بازی بازی را به پایان می رساند.
LiveData یک کلاس دارنده داده قابل مشاهده است که از چرخه حیات آگاه است. برای مثال، میتوانید یک LiveData حول امتیاز فعلی در برنامه GuessTheWord بپیچید. در این کد لبه با چندین ویژگی LiveData آشنا می شوید:
-
LiveDataقابل مشاهده است، به این معنی که هنگامی که داده های نگهداری شده توسط شیLiveDataتغییر می کند، یک ناظر مطلع می شود. -
LiveDataداده ها را نگه می دارد.LiveDataیک بسته بندی است که می تواند با هر داده ای استفاده شود -
LiveDataاز چرخه حیات آگاه است، به این معنی که فقط ناظرانی را که در یک وضعیت چرخه حیات فعال هستند مانندSTARTEDیاRESUMEDبه روز می کند.
در این کار، میآموزید که چگونه با تبدیل امتیاز فعلی و دادههای کلمه فعلی در GameViewModel به LiveData ، هر نوع داده را در اشیاء LiveData قرار دهید. در کار بعدی، یک ناظر به این اشیاء LiveData اضافه میکنید و یاد میگیرید که چگونه LiveData مشاهده کنید.
مرحله 1: امتیاز و کلمه را برای استفاده از LiveData تغییر دهید
- در زیر بسته
screens/game، فایلGameViewModelباز کنید. - نوع
scoreمتغیرها وwordرا بهMutableLiveDataتغییر دهید.
MutableLiveDataیکLiveDataاست که مقدار آن قابل تغییر است.MutableLiveDataیک کلاس عمومی است، بنابراین باید نوع داده ای که در آن نگهداری می شود را مشخص کنید.
// The current word
val word = MutableLiveData<String>()
// The current score
val score = MutableLiveData<Int>()- در
GameViewModel، در داخل بلوکinit،scoreوwordرا مقداردهی اولیه کنید. برای تغییر مقدار متغیرLiveData، از متدsetValue()روی متغیر استفاده می کنید. در Kotlin، می توانیدsetValue()با استفاده از ویژگیvalueفراخوانی کنید.
init {
word.value = ""
score.value = 0
...
}مرحله 2: مرجع شی LiveData را به روز کنید
متغیرهای score و word اکنون از نوع LiveData هستند. در این مرحله با استفاده از ویژگی value ، ارجاعات را به این متغیرها تغییر می دهید.
- در
GameViewModel، در متدonSkip()scoreبهscore.valueتغییر دهید. به خطای احتمالnullبودنscoreتوجه کنید. در مرحله بعد این خطا را رفع می کنید. - برای رفع خطا، یک چک
nullبهscore.valueدرonSkip()اضافه کنید. سپس تابعminus()را درscoreفراخوانی می کند که تفریق را با امنیتnullانجام می دهد.
fun onSkip() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.minus(1)
}
nextWord()
}- متد
onCorrect()را به همین ترتیب به روز کنید: یک چکnullبه متغیرscoreاضافه کنید و از تابعplus()استفاده کنید.
fun onCorrect() {
if (!wordList.isEmpty()) {
score.value = (score.value)?.plus(1)
}
nextWord()
}- در
GameViewModel، در متدnextWord()wordreference را بهwordتغییر دهید.value.
private fun nextWord() {
if (!wordList.isEmpty()) {
//Select and remove a word from the list
word.value = wordList.removeAt(0)
}
}- در
GameFragment، در داخل متدupdateWordText()مرجع را بهviewModel.wordبهviewModelتغییر دهید.word.value.
/** Methods for updating the UI **/
private fun updateWordText() {
binding.wordText.text = viewModel.word.value
}- در
GameFragment، در داخل متدupdateScoreText()، مرجع را بهviewModel.scoreبهviewModelتغییر دهید.score.value.
private fun updateScoreText() {
binding.scoreText.text = viewModel.score.value.toString()
}- در
GameFragment، در داخل متدgameFinished()، مرجع را بهviewModel.scoreبهviewModelتغییر دهید.score.value. چک ایمنیnullمورد نیاز را اضافه کنید.
private fun gameFinished() {
Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
val action = GameFragmentDirections.actionGameToScore()
action.score = viewModel.score.value?:0
NavHostFragment.findNavController(this).navigate(action)
}- مطمئن شوید که هیچ خطایی در کد شما وجود ندارد. برنامه خود را کامپایل و اجرا کنید. عملکرد برنامه باید مانند قبل باشد.
این کار ارتباط نزدیکی با کار قبلی دارد، جایی که شما داده های امتیاز و کلمه را به آبجکت های LiveData تبدیل کردید. در این کار، اشیاء Observer را به آن اشیاء LiveData متصل می کنید.
- در
GameFragment,در داخل متدonCreateView()، یک شیObserverرا به شیLiveDataبرای امتیاز فعلی،viewModel.scoreمتصل کنید. از متدobserve()استفاده کنید و کد را بعد از مقداردهی اولیهviewModelقرار دهید. از عبارت lambda برای ساده کردن کد استفاده کنید. (یک عبارت لامبدا یک تابع ناشناس است که اعلان نمی شود، اما بلافاصله به عنوان یک عبارت ارسال می شود.)
viewModel.score.observe(this, Observer { newScore ->
}) ارجاع به Observer را حل کنید. برای انجام این کار، روی Observer کلیک کنید، Alt+Enter ( Option+Enter در مک) را فشار دهید و androidx.lifecycle.Observer را وارد کنید.
- ناظری که شما به تازگی ایجاد کرده اید، زمانی که داده های نگهداری شده توسط شی
LiveDataمشاهده شده تغییر می کند، یک رویداد دریافت می کند. در داخل مشاهده گر، امتیازTextViewبا امتیاز جدید به روز کنید.
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})- یک شی
Observerرا به شیء فعلیLiveDataمتصل کنید. این کار را به همان روشی انجام دهید که یک شیObserverرا به امتیاز فعلی متصل کردید.
/** Setting up LiveData observation relationship **/
viewModel.word.observe(this, Observer { newWord ->
binding.wordText.text = newWord
})وقتی مقدار score یا word تغییر می کند، score یا word نمایش داده شده روی صفحه اکنون به طور خودکار به روز می شود.
- در
GameFragment، متدهایupdateWordText()وupdateScoreText()و تمام ارجاعات به آنها را حذف کنید. شما دیگر به آنها نیاز ندارید، زیرا نماهای متنی با روش های مشاهده گرLiveDataبه روز می شوند. - برنامه خود را اجرا کنید برنامه بازی شما باید دقیقاً مانند قبل کار کند، اما اکنون از ناظرهای
LiveDataوLiveDataاستفاده می کند.
کپسولاسیون راهی برای محدود کردن دسترسی مستقیم به برخی از فیلدهای یک شی است. وقتی یک شی را کپسوله میکنید، مجموعهای از روشهای عمومی را نشان میدهید که فیلدهای داخلی خصوصی را تغییر میدهند. با استفاده از کپسوله سازی، شما کنترل می کنید که چگونه کلاس های دیگر این فیلدهای داخلی را دستکاری می کنند.
در کد فعلی شما، هر کلاس خارجی میتواند متغیرهای score و word را با استفاده از ویژگی value تغییر دهد، برای مثال با استفاده از viewModel.score.value . ممکن است در برنامهای که در این Codelab توسعه میدهید مهم نباشد، اما در یک برنامه تولیدی، میخواهید روی دادههای موجود در اشیاء ViewModel کنترل داشته باشید.
فقط ViewModel باید داده های برنامه شما را ویرایش کند. اما کنترلکنندههای رابط کاربری باید دادهها را بخوانند، بنابراین فیلدهای داده نمیتوانند کاملاً خصوصی باشند. برای کپسوله کردن داده های برنامه خود، از هر دو شی MutableLiveData و LiveData استفاده می کنید.
MutableLiveData در مقابل LiveData :
- همانطور که از نام آن پیداست، داده های موجود در یک شی
MutableLiveDataقابل تغییر هستند. در داخلViewModel، داده ها باید قابل ویرایش باشند، بنابراین ازMutableLiveDataاستفاده می کند. - داده ها در یک شی
LiveDataقابل خواندن هستند، اما تغییر نمی کنند. از خارج ازViewModel، داده ها باید قابل خواندن باشند، اما قابل ویرایش نباشند، بنابراین داده ها باید به صورتLiveDataدر معرض نمایش قرار گیرند.
برای اجرای این استراتژی، از ویژگی پشتیبان Kotlin استفاده می کنید. یک ویژگی پشتیبان به شما امکان می دهد چیزی را از یک گیرنده غیر از شی دقیق برگردانید. در این کار، یک ویژگی پشتیبان برای اشیاء score و word در برنامه GuessTheWord پیاده سازی می کنید.
یک ویژگی پشتیبان به امتیاز و کلمه اضافه کنید
- در
GameViewModel، شیscoreفعلی راprivateکنید. - برای پیروی از قرارداد نامگذاری مورد استفاده در ویژگی های پشتیبان،
scoreبه_scoreتغییر دهید. ویژگی_scoreاکنون نسخه قابل تغییر امتیاز بازی است که به صورت داخلی مورد استفاده قرار می گیرد. - یک نسخه عمومی از نوع
LiveDataبه نامscoreایجاد کنید.
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>- شما یک خطای اولیه را مشاهده می کنید. این خطا به این دلیل رخ می دهد که در داخل
GameFragment،scoreیک مرجعLiveDataاست وscoreدیگر نمی تواند به تنظیم کننده آن دسترسی داشته باشد. برای کسب اطلاعات بیشتر در مورد گترها و ستترها در کاتلین، به گترها و ستترها مراجعه کنید.
برای رفع خطا، متدget()را برای شیscoreدرGameViewModelلغو کنید و ویژگی پشتیبان_scoreبرگردانید.
val score: LiveData<Int>
get() = _score- در
GameViewModel، ارجاعscoreرا به نسخه داخلی قابل تغییر آن،_scoreتغییر دهید.
init {
...
_score.value = 0
...
}
...
fun onSkip() {
if (!wordList.isEmpty()) {
_score.value = (score.value)?.minus(1)
}
...
}
fun onCorrect() {
if (!wordList.isEmpty()) {
_score.value = (score.value)?.plus(1)
}
...
}-
wordشی را به_wordتغییر نام دهید و یک ویژگی پشتیبان برای آن اضافه کنید، همانطور که برای شیscoreانجام دادید.
// The current word
private val _word = MutableLiveData<String>()
val word: LiveData<String>
get() = _word
...
init {
_word.value = ""
...
}
...
private fun nextWord() {
if (!wordList.isEmpty()) {
//Select and remove a word from the list
_word.value = wordList.removeAt(0)
}
}کار عالی، شما word و score اشیاء LiveData را کپسوله کرده اید.
وقتی کاربر روی دکمه پایان بازی ضربه میزند، برنامه فعلی شما به صفحه امتیاز حرکت میکند. همچنین میخواهید وقتی بازیکنان تمام کلمات را چرخانده باشند، برنامه به صفحه امتیاز حرکت کند. بعد از اینکه بازیکنان با کلمه آخر تمام شدند، می خواهید بازی به طور خودکار تمام شود تا کاربر مجبور نباشد روی دکمه ضربه بزند.
برای پیادهسازی این عملکرد، باید یک رویداد راهاندازی شود و زمانی که همه کلمات نشان داده شدند، از ViewModel به قطعه ارسال شود. برای انجام این کار، از الگوی مشاهدهگر LiveData برای مدلسازی یک رویداد تمامشده بازی استفاده میکنید.
الگوی ناظر
الگوی مشاهده گر یک الگوی طراحی نرم افزار است. این ارتباط بین اشیاء را مشخص می کند: یک قابل مشاهده («موضوع» مشاهده) و ناظران . قابل مشاهده شیئی است که ناظران را از تغییرات حالت خود آگاه می کند.

در مورد LiveData در این برنامه، قابل مشاهده (موضوع) شی LiveData است و ناظرها روشهایی هستند که در کنترلکنندههای UI، مانند قطعات، وجود دارد. هر زمان که دادههای پیچیده شده در LiveData تغییر کنند، تغییر حالت اتفاق میافتد. کلاس های LiveData در برقراری ارتباط از ViewModel به قطعه بسیار مهم هستند.
مرحله 1: از LiveData برای شناسایی یک رویداد بازی استفاده کنید
در این کار، از الگوی مشاهدهگر LiveData برای مدلسازی یک رویداد تمامشده بازی استفاده میکنید.
- در
GameViewModel، یک شیBooleanMutableLiveDataبه نام_eventGameFinishایجاد کنید. این شی رویداد پایان بازی را برگزار می کند. - پس از مقداردهی اولیه شی
_eventGameFinish، یک ویژگی پشتیبان به نامeventGameFinishایجاد و مقداردهی اولیه کنید.
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
get() = _eventGameFinish- در
GameViewModel، یک متدonGameFinish()اضافه کنید. در این روش، رویداد پایان بازی،eventGameFinishرا رویtrueتنظیم کنید.
/** Method for the game completed event **/
fun onGameFinish() {
_eventGameFinish.value = true
}- در
GameViewModel، در داخل متدnextWord()، اگر لیست کلمات خالی بود، بازی را تمام کنید.
private fun nextWord() {
if (wordList.isEmpty()) {
onGameFinish()
} else {
//Select and remove a _word from the list
_word.value = wordList.removeAt(0)
}
}- در
GameFragment، داخلonCreateView()، پس از مقداردهی اولیهviewModel، یک مشاهده گر را بهeventGameFinishمتصل کنید. از متدobserve()استفاده کنید. در داخل تابع لامبدا، متدgameFinished()فراخوانی کنید.
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
if (hasFinished) gameFinished()
})- برنامه خود را اجرا کنید، بازی را انجام دهید و تمام کلمات را مرور کنید. برنامه بهجای ماندن در بخش بازی تا زمانی که روی پایان بازی ضربه بزنید، بهطور خودکار به صفحه امتیاز حرکت میکند.
پس از خالی شدن فهرست کلمات،eventGameFinishتنظیم میشود، متد مشاهدهگر مرتبط در قطعه بازی فراخوانی میشود و برنامه به قطعه صفحه هدایت میشود. - کدی که اضافه کردید یک مشکل چرخه حیات را معرفی کرده است. برای درک موضوع، در کلاس
GameFragment، کد پیمایش را در متدgameFinished()توضیح دهید. مطمئن شوید که پیامToastرا در روش نگه دارید.
private fun gameFinished() {
Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
// val action = GameFragmentDirections.actionGameToScore()
// action.score = viewModel.score.value?:0
// NavHostFragment.findNavController(this).navigate(action)
}
- برنامه خود را اجرا کنید، بازی را انجام دهید و تمام کلمات را مرور کنید. یک پیام نان تست که می گوید "بازی به تازگی تمام شد" به طور خلاصه در پایین صفحه بازی ظاهر می شود که رفتار مورد انتظار است.
اکنون دستگاه یا شبیه ساز را بچرخانید. نان تست دوباره نمایش داده می شود! دستگاه را چند بار دیگر بچرخانید و احتمالاً هر بار نان تست را خواهید دید. این یک اشکال است، زیرا نان تست فقط یک بار، زمانی که بازی تمام شد، نمایش داده شود. نان تست نباید هر بار که قطعه دوباره ایجاد می شود نمایش داده شود. شما این مشکل را در کار بعدی حل می کنید.
|
|
مرحله 2: رویداد پایان بازی را بازنشانی کنید
معمولاً LiveData فقط در صورت تغییر داده ها به ناظران به روز رسانی می کند. یک استثنا در این رفتار این است که ناظران همچنین بهروزرسانیهایی را دریافت میکنند که ناظر از حالت غیرفعال به حالت فعال تغییر کند.
به همین دلیل است که نان تست تمام شده بازی به طور مکرر در برنامه شما فعال می شود. وقتی قطعه بازی پس از چرخش صفحه دوباره ایجاد می شود، از حالت غیرفعال به حالت فعال می رود. مشاهدهگر در قطعه مجدداً به ViewModel موجود متصل میشود و دادههای جاری را دریافت میکند. متد gameFinished() دوباره راه اندازی می شود و نان تست نمایش داده می شود.
در این کار، با تنظیم مجدد پرچم eventGameFinish در GameViewModel ، این مشکل را برطرف کرده و نان تست را تنها یک بار نمایش می دهید.
- در
GameViewModel، یک متدonGameFinishComplete()برای بازنشانی رویداد پایان یافته بازی،_eventGameFinishاضافه کنید.
/** Method for the game completed event **/
fun onGameFinishComplete() {
_eventGameFinish.value = false
}- در
GameFragment، در انتهایgameFinished()onGameFinishComplete()در شیviewModelفراخوانی کنید. (کد پیمایش را فعلاً درgameFinished()که نظر داده شده است بگذارید.)
private fun gameFinished() {
...
viewModel.onGameFinishComplete()
}- برنامه را اجرا کنید و بازی را انجام دهید. تمام کلمات را مرور کنید، سپس جهت صفحه نمایش دستگاه را تغییر دهید. نان تست فقط یک بار نمایش داده می شود.
- در
GameFragment، در متدgameFinished()، کد پیمایش را از حالت کامنت بردارید.
برای لغو نظر در اندروید استودیو، خطوطی را که نظر داده میشوند انتخاب کنید وControl+/(Command+/در مک) را فشار دهید.
private fun gameFinished() {
Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
val action = GameFragmentDirections.actionGameToScore()
action.score = viewModel.score.value?:0
findNavController(this).navigate(action)
viewModel.onGameFinishComplete()
}اگر Android Studio از شما خواسته است، androidx.navigation.fragment.NavHostFragment.findNavController را وارد کنید.
- برنامه را اجرا کنید و بازی را انجام دهید. مطمئن شوید که برنامه به طور خودکار پس از مرور همه کلمات به صفحه امتیاز نهایی هدایت می شود.
|
|
کار بزرگ! برنامه شما از LiveData استفاده میکند تا یک رویداد تمامشده بازی را راهاندازی کند تا از GameViewModel به قطعه بازی که لیست کلمات خالی است، ارتباط برقرار کند. قطعه بازی سپس به قطعه امتیاز حرکت می کند.
در این کار، امتیاز را به یک شی LiveData در ScoreViewModel تغییر میدهید و یک مشاهدهگر را به آن متصل میکنید. این کار شبیه کاری است که هنگام افزودن LiveData به GameViewModel انجام دادید.
شما این تغییرات را برای کامل شدن در ScoreViewModel انجام می دهید، به طوری که تمام داده های برنامه شما از LiveData استفاده می کند.
- در
ScoreViewModel، نوع متغیرscoreرا بهMutableLiveDataتغییر دهید. نام آن را طبق قرارداد به_scoreتغییر دهید و یک ویژگی پشتیبان اضافه کنید.
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
get() = _score- در
ScoreViewModel، داخل بلوکinit،_scoreرا مقداردهی اولیه کنید. شما می توانید گزارش را به دلخواه حذف یا در بلوکinitبگذارید.
init {
_score.value = finalScore
}- در
ScoreFragment، در داخلonCreateView()، پس از مقداردهی اولیهviewModel، یک ناظر برای شی امتیازLiveDataمتصل کنید. در داخل عبارت لامبدا، مقدار امتیاز را روی نمای متن امتیاز تنظیم کنید. کدی را که مستقیماً نمای متن را با مقدار امتیاز تخصیص می دهد ازViewModelحذف کنید.
کد برای اضافه کردن:
// Add observer for score
viewModel.score.observe(this, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})کد برای حذف:
binding.scoreText.text = viewModel.score.toString()وقتی Android Studio از شما خواسته شد، androidx.lifecycle.Observer وارد کنید.
- برنامه خود را اجرا کنید و بازی را انجام دهید. این برنامه باید مانند قبل کار کند، اما اکنون از
LiveDataو یک ناظر برای به روز رسانی امتیاز استفاده می کند.
در این کار، یک دکمه Play Again را به صفحه امتیاز اضافه میکنید و با استفاده از رویداد LiveData ، شنونده کلیک آن را پیادهسازی میکنید. دکمه یک رویداد را برای حرکت از صفحه امتیاز به صفحه بازی راه اندازی می کند.
کد شروع برنامه شامل دکمه Play Again است، اما دکمه پنهان است.
- در
res/layout/score_fragment.xml، برای دکمهplay_again_button، مقدار مشخصهvisibilityرا بهvisibleتغییر دهید.
<Button
android:id="@+id/play_again_button"
...
android:visibility="visible"
/>- در
ScoreViewModel، یک شیLiveDataاضافه کنید تا یکBooleanبه نام_eventPlayAgainنگه دارد. این شیء برای ذخیره رویدادLiveDataبرای حرکت از صفحه امتیاز به صفحه بازی استفاده می شود.
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
get() = _eventPlayAgain- در
ScoreViewModel، روش هایی را برای تنظیم و بازنشانی رویداد تعریف کنید،_eventPlayAgain.
fun onPlayAgain() {
_eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
_eventPlayAgain.value = false
}- در
ScoreFragment، یک ناظر برایeventPlayAgainاضافه کنید. کد را در انتهایonCreateView()قبل از عبارتreturnقرار دهید. در داخل عبارت lambda، به صفحه بازی بازگردید وeventPlayAgainرا بازنشانی کنید.
// Navigates back to game when button is pressed
viewModel.eventPlayAgain.observe(this, Observer { playAgain ->
if (playAgain) {
findNavController().navigate(ScoreFragmentDirections.actionRestart())
viewModel.onPlayAgainComplete()
}
})وقتی Android Studio از شما خواسته شد androidx.navigation.fragment.findNavController وارد کنید.
- در
ScoreFragment، داخلonCreateView()یک کلیک شنونده به دکمه PlayAgain اضافه کنید وviewModel.onPlayAgain()را فراخوانی کنید.
binding.playAgainButton.setOnClickListener { viewModel.onPlayAgain() }- برنامه خود را اجرا کنید و بازی را انجام دهید. پس از پایان بازی، صفحه امتیاز، امتیاز نهایی و دکمه Play Again را نشان می دهد. روی دکمه PlayAgain ضربه بزنید و برنامه به صفحه بازی هدایت می شود تا بتوانید دوباره بازی را انجام دهید.

کار خوب! شما معماری برنامه خود را برای استفاده از اشیاء LiveData در ViewModel تغییر دادید و ناظران را به اشیاء LiveData متصل کردید. LiveData هنگامی که مقدار نگهداری شده توسط LiveData تغییر می کند، به اشیاء ناظر اطلاع می دهد.
پروژه اندروید استودیو: GuessTheWord
LiveData
-
LiveDataیک کلاس دارنده داده قابل مشاهده است که از چرخه حیات آگاه است، یکی از اجزای معماری Android . - میتوانید از
LiveDataبرای فعال کردن رابط کاربری خود برای بهروزرسانی خودکار هنگام بهروزرسانی دادهها استفاده کنید. -
LiveDataقابل مشاهده است، به این معنی که یک ناظر مانند یک فعالیت یا یک قطعه می تواند هنگام تغییر داده های نگهداری شده توسط شیLiveDataمطلع شود. -
LiveDataداده ها را نگه می دارد. این یک بسته بندی است که می تواند با هر داده ای استفاده شود. -
LiveDataاز چرخه حیات آگاه است، به این معنی که فقط ناظرانی را که در یک وضعیت چرخه حیات فعال هستند مانندSTARTEDیاRESUMEDبه روز می کند.
برای افزودن LiveData
- نوع متغیرهای داده در
ViewModelرا بهLiveDataیاMutableLiveDataتغییر دهید.
MutableLiveData یک شی LiveData است که مقدار آن قابل تغییر است. MutableLiveData یک کلاس عمومی است، بنابراین باید نوع داده ای که در آن نگهداری می شود را مشخص کنید.
- برای تغییر مقدار داده های نگهداری شده توسط
LiveData، از متدsetValue()در متغیرLiveDataاستفاده کنید.
برای کپسوله کردن LiveData
-
LiveDataداخلViewModelباید قابل ویرایش باشد. در خارج ازViewModel،LiveDataباید قابل خواندن باشد. این را می توان با استفاده از ویژگی پشتیبان Kotlin پیاده سازی کرد. - ویژگی پشتیبان Kotlin به شما امکان می دهد چیزی را از یک گیرنده غیر از شی دقیق برگردانید.
- برای کپسوله کردن
LiveData، ازMutableLiveDataprivateدر داخلViewModelاستفاده کنید و یک ویژگی پشتیبانLiveDataرا خارج ازViewModelبرگردانید.
LiveData قابل مشاهده
-
LiveDataاز یک الگوی ناظر پیروی می کند. «مشاهدهپذیر» شیLiveDataاست و ناظرها روشهایی هستند که در کنترلکنندههای UI، مانند قطعهها هستند. هر زمان که دادههای پیچیده شده درLiveDataتغییر کند، روشهای مشاهدهگر در کنترلکنندههای UI مطلع میشوند. - برای اینکه
LiveDataقابل مشاهده باشد، با استفاده از متدobserve()یک شی مشاهده گر را به مرجعLiveDataدر مشاهدهگرها (مانند فعالیت ها و قطعات) متصل کنید. - این الگوی مشاهده گر
LiveDataمی تواند برای برقراری ارتباط ازViewModelبه کنترل کننده های UI استفاده شود.
دوره بی ادبی:
مستندات توسعه دهنده اندروید:
دیگر:
- دارایی پشتیبان در Kotlin
این بخش، تکالیف احتمالی را برای دانشآموزانی که در این آزمایشگاه کد به عنوان بخشی از دورهای که توسط یک مربی هدایت میشود، کار میکنند، فهرست میکند. این وظیفه مربی است که موارد زیر را انجام دهد:
- در صورت نیاز تکالیف را تعیین کنید.
- نحوه ارسال تکالیف را با دانش آموزان در میان بگذارید.
- تکالیف را نمره دهید.
مربیان میتوانند از این پیشنهادات به اندازهای که میخواهند استفاده کنند، و باید با خیال راحت هر تکلیف دیگری را که فکر میکنند مناسب است، محول کنند.
اگر به تنهایی از طریق این کدها کار می کنید، از این تکالیف برای آزمایش دانش خود استفاده کنید.
به این سوالات پاسخ دهید
سوال 1
چگونه LiveData ذخیره شده در ViewModel را کپسوله می کنید تا اشیاء خارجی بتوانند داده ها را بدون به روز رسانی بخوانند؟
- در داخل شی
ViewModel، نوع داده داده ها را بهprivateLiveDataتغییر دهید. از یک ویژگی پشتیبان برای نمایش داده های فقط خواندنی از نوعMutableLiveDataاستفاده کنید. - در داخل شی
ViewModel، نوع داده داده ها را بهMutableLiveDataprivateتغییر دهید. از یک ویژگی پشتیبان برای نمایش داده های فقط خواندنی از نوعLiveDataاستفاده کنید. - در داخل کنترلر UI، نوع داده داده ها را به
MutableLiveDataprivateتغییر دهید. از یک ویژگی پشتیبان برای نمایش داده های فقط خواندنی از نوعLiveDataاستفاده کنید. - در داخل شی
ViewModel، نوع داده داده ها را بهLiveDataتغییر دهید. از یک ویژگی پشتیبان برای نمایش داده های فقط خواندنی از نوعLiveDataاستفاده کنید.
سوال 2
اگر کنترلر UI در کدام یک از حالت های زیر باشد، LiveData یک کنترلر UI (مانند یک قطعه) را به روز می کند؟
- از سر گرفته شد
- در پس زمینه
- مکث کرد
- متوقف شد
سوال 3
در الگوی مشاهدهگر LiveData ، آیتم قابل مشاهده (آنچه مشاهده میشود) چیست؟
- روش مشاهده گر
- داده ها در یک شی
LiveData - کنترلر رابط کاربری
- شی
ViewModel
درس بعدی را شروع کنید:
برای پیوند به سایر کدهای این دوره، به صفحه فرود کد لبههای کد پایه Android Kotlin Fundamentals مراجعه کنید.




