این کد لبه بخشی از دوره آموزشی 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()
،word
reference را به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()
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()
observer استفاده کنید و کد را بعد از مقداردهی اولیه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(updateScoreText()
و تمام ارجاعات به آنها را حذف کنید. شما دیگر به آنها نیاز ندارید، زیرا نماهای متنی با روش های مشاهدهLiveData
به روز می شوند. - برنامه خود را اجرا کنید برنامه بازی شما باید دقیقاً مانند قبل کار کند، اما اکنون از ناظران
LiveData
وLiveData
استفاده می کند.
کپسولاسیون راهی برای محدود کردن دسترسی مستقیم به برخی از فیلدهای یک شی است. وقتی یک شی را کپسوله میکنید، مجموعهای از روشهای عمومی را نشان میدهید که فیلدهای داخلی خصوصی را تغییر میدهند. با استفاده از کپسوله کردن، شما کنترل می کنید که کلاس های دیگر چگونه این فیلدهای داخلی را دستکاری می کنند.
در کد فعلی شما، هر کلاس خارجی می تواند متغیرهای score
و word
را با استفاده از ویژگی value
تغییر دهد، برای مثال با استفاده از viewModel.score.value
. ممکن است در برنامهای که در این کد لبه توسعه میدهید مهم نباشد، اما در یک برنامه تولیدی، میخواهید روی دادههای موجود در اشیاء 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
دیگر نمی تواند به تنظیم کننده آن دسترسی داشته باشد. برای کسب اطلاعات بیشتر در مورد گیرنده ها و ستترها در کاتلین، به Getters and Setters مراجعه کنید.
برای رفع خطا، متد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
، یک شیBoolean
MutableLiveData
به نام_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()
observer استفاده کنید. در داخل تابع لامبدا،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
، ازMutableLiveData
private
در داخلViewModel
استفاده کنید و یک ویژگی پشتیبانLiveData
را خارج ازViewModel
.
LiveData قابل مشاهده
-
LiveData
از یک الگوی ناظر پیروی می کند. «مشاهدهپذیر» شیLiveData
است و ناظرها روشهایی هستند که در کنترلکنندههای UI، مانند قطعات، هستند. هر زمان که دادههای پیچیده شده درLiveData
تغییر کند، روشهای مشاهدهگر در کنترلکنندههای UI مطلع میشوند. - برای اینکه
LiveData
قابل مشاهده باشد، با استفاده از متد Observer() یک شی مشاهده گر را به مرجعLiveData
در مشاهدهگرها (مانند فعالیت ها و قطعات) متصلobserve()
. - این الگوی مشاهده
LiveData
می تواند برای برقراری ارتباط ازViewModel
به کنترل کننده های UI استفاده شود.
دوره بی ادبی:
مستندات توسعه دهنده اندروید:
دیگر:
- پشتیبان ملک در کاتلین
این بخش، تکالیف احتمالی را برای دانشآموزانی که در این آزمایشگاه کد به عنوان بخشی از دورهای که توسط یک مربی هدایت میشود، فهرست میکند. این وظیفه مربی است که موارد زیر را انجام دهد:
- در صورت نیاز تکالیف را تعیین کنید.
- نحوه ارسال تکالیف را با دانش آموزان در میان بگذارید.
- تکالیف را درجه بندی کنید.
مربیان میتوانند از این پیشنهادات به اندازهای که میخواهند استفاده کنند، و باید با خیال راحت هر تکلیف دیگری را که فکر میکنند مناسب است به آنها اختصاص دهند.
اگر به تنهایی بر روی این کدها کار می کنید، از این تکالیف برای آزمایش دانش خود استفاده کنید.
یه این سوالات پاسخ دهید
سوال 1
چگونه می توان LiveData
ذخیره شده در ViewModel
را کپسوله کرد تا اشیاء خارجی بتوانند داده ها را بدون امکان به روز رسانی بخوانند؟
- در داخل شی
ViewModel
، نوع داده داده ها را بهprivate
LiveData
تغییر دهید. از یک ویژگی پشتیبان برای نمایش داده های فقط خواندنی از نوعMutableLiveData
استفاده کنید. - در داخل شی
ViewModel
، نوع داده داده ها را بهMutableLiveData
private
تغییر دهید. از یک ویژگی پشتیبان برای نمایش داده های فقط خواندنی از نوعLiveData
استفاده کنید. - در داخل کنترلر UI، نوع داده داده ها را به
MutableLiveData
private
تغییر دهید. از یک ویژگی پشتیبان برای نمایش داده های فقط خواندنی از نوعLiveData
استفاده کنید. - در داخل شی
ViewModel
، نوع داده داده ها را بهLiveData
تغییر دهید. از یک ویژگی پشتیبان برای نمایش داده های فقط خواندنی از نوعLiveData
استفاده کنید.
سوال 2
اگر کنترلر UI در کدام یک از حالت های زیر باشد، LiveData
یک کنترلر UI (مانند یک قطعه) را به روز می کند؟
- از سر گرفته شد
- در پس زمینه
- مکث شد
- متوقف شد
سوال 3
در الگوی ناظر LiveData
، آیتم قابل مشاهده (آنچه مشاهده می شود) چیست؟
- روش مشاهده گر
- داده های موجود در یک شی
LiveData
- کنترلر رابط کاربری
- شی
ViewModel
درس بعدی را شروع کنید:
برای پیوند به دیگر کدهای این دوره، به صفحه فرود کد لبههای کد پایه Android Kotlin Fundamentals مراجعه کنید.