به نام خدا

یادمه پست اموزش mvvm - قسمت اول رو آبانماه پارسال گذاشتم چه زود میگذره

بگذریم. توی قسمت اول یاد گرفتیم که DataBinding چیه و چجوری باهاش کار کنیم. داستان DataBinding فراتر از اون چیزی هست که توضیح دادم و در ادامه آموزش ها با تمامی ویژگی هاش آشنا میشیم

قصد دارم امروز سایر کامپوننت های حوزه mvvm اشنا بشیم:

  • ViewModel
  • LiveData

اگه بخوایم ویو مدل رو تعریف کنیم ویو مدل یه واسط بین مدل و ویو هست به این صورت که دیتایی که توی مدل داریم رو با ویو مدل روی ویو ست میکنیم

از این به بعد قراره توی معماری mvvm توی ویو مدل هیچ اطلاعی از ویو نداشته باشید و همچنین توی مدل هم هیچ اطلاعی از ویو مدل نداشته باشید

یعنی داستان یه طرفه است به این صورت که ویو از ویومدل خبر داره و ویومدل از مدل.

پس ویومدل یه کلاس معمولی هست که قراره توش توابع منطقی برنامه رو بریزیم مثلا توی مدل یه متغیر زمان داریم و توی ویومدل اون متغیر رو به شکل شمسی در میاریم و در نهایت با کلاس ویو روی ویوی مربوطه ست میکنیم.

نکته: توی ویو مدل نباید هیچ اثری از activity , fragment , context باشه اما میتونید برای استفاده از یه سری سرویس های اندروید از ApplicationContext استفاده کنید و برای اینکه به اپلیکیشن کانتکست دسترسی داشته باشید باید کلاس ویومدلتون از AndroidViewModel ارث بری کرده باشه.

یه خورده وارد فاز فنی داستان اگه بشیم میبینیم که وقتی کد زیر رو توی onCreate اکتیوتی یا فرگمنت خودمون قرار میدیم:

ViewModelProviders.of(<Your UI controller>).get(<Your ViewModel>.class)

به این شکل کار میکنه که وقتی دفعه اول اجرا میشه یه instance از کلاس ویو مدل ساخته میشه که به صورت استاتیک ذخیره میشه و وقتی که onCreate دوباره صدا زده میشه (مثلا صفحه گوشی میچرخه) چون کلاس ویومدل ما استاتیک بوده، دیتای داخلش دست نخورده و حفظ شده باقی میمونه.

دقت کنید که ویومدل متناسب با اکتیویتی رو به شما میده یعنی اگه شما یه MainActivity داشته باشید که یه دیتایی توش باشه و از اونجا یه فرگمنت رو لود کنید و توی فرگمنت هم به تابع of همون اکتیوتی MainActivty رو بدید، ویومدلی که توش دیتا ذخیره شده به شما برگردونده میشه.

LiveData

همانطور که در ابتدای مطلب توضیح دادم، و گفتم که میتونید یه متغییر استرینگ رو به یه ویو بایند کنید باید عرض کنم که استرینگ معمولی نمیتونه چنین ویژگی رو براتون فراهم کنه و لازمه که شما از یه کامپوننت جدید به اسم LiveData استفاده کنید

نمیخوام زیاد وارد جزئیات بشم ولی یه متغییر Observable هست که به محض تغییر اون Observer هاش صدا زده میشه که به توضیح ساده ترش میشه همونی که میخواستم به محض تغییر دیتا، ویو هم تغییر میکنه

بایند کردن یک LiveData به یک View

به دو روش میشه اینکارو کرد:

  • از طریق DataBinding که پیاده سازیش رو توی قسمت اول گفتیم و میمونه قسمت تکمیلیش
  • از طریق Observe کردن LiveData

کار راحت و تمیز تر (البته بستگی به نیازداره) اینه که شما از دیتابایندینگ که در جلسه اول آموزش دادیم استفاده کنید و در تگ layout از کد های زیر بهره ببرید:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="temp" type="com.vogella.android.databinding.TemperatureData"/> 
   </data>
   <LinearLayout 
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{temp.location}"/>
       <TextView
        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="@{temp.celsius}"/>
   </LinearLayout>
</layout>

خب اگه دقت کنید توی لایوت یه تگ به اسم دیتا قرار میدیم و توش متغییر هایی (که ویومدل ها هستن) رو مینویسیم

بعد از این باید برگردیم به کد جاوا یا کاتلین و توی onCreate مون اون متغییری که توی xml ازش اسم بردیم رو مقدار بدیم

TemperatureData temperatureData = ViewModelProviders.of(this).get(TemperatureData.class);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setTemp(temperatureData);

و احتمالا تا الان منتظر کلاس TemperatureData هستید:

class TemperatureData {
   public final ObservableField<String> celsius = new ObservableField<>();
   public final ObservableField<String> location =  new ObservableField<>();
}

این یه راه بایند کردن بود که توی xml مستقیما text رو به متغییر بایند میکنید

راه دوم) بایند کردن دیتا به ویو با استفاده از کد

onCreate کلاس ویوی شما (کاتلین)

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

        // Other code to setup the activity...

        // Get the ViewModel.
        model = ViewModelProviders.of(this).get(NameViewModel::class.java)


        // 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)
    }

و این هم کلاس NameViewModel

class NameViewModel : ViewModel() {

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

    // Rest of the ViewModel...
}

حالا هر موقع که currentName  تغییر کنه تکست ویوی nameTextView واکنش نشون میده و تغییر میکنه

تا الان سه مبحث اصلی ViewModel - LiveData - DataBinding رو یادگرفتیم.

از سایت های خارجی و سورس هایی که توی گیتهاب هست استفاده کنید تا کاملا مطلب براتون جا بیفته

اگه سوالی هم بود بپرسید بلد باشم جواب میدم