آموزش بایند کردن view های لایه به مولفه های معماری اندروید ، کتابخانه AndroidX شامل مولفه های معماری می باشد که به شما اجازه پیاده سازی اپلیکیشنی تست پذیر ، قدرتمند و قابل نگهداری را می دهد.
نکته :
منظور از مولفه های معماری اندروید درواقع استفاده از مولفه هایی مانند LiveData ، ViewModel و Room و مولفه های lifecycle-aware است که اپلیکیشن شما را بسیار قوی و تست پذیر میکند به علاوه قابل نگهداری که برای پروژه های بزرگ بسیار حائز اهمیت است.برای اطلاعات بیشتر درباره مولفه های معماری اندروید این مقاله از اندروید را مطالعه کنید.
کتابخانه دیتا بایندینگ با تمامی مولفه های معماری اندروید سازگاری دارد .لایه های درون اپلیکشین شما می توانند به راحتی به مولفه های معماری اندروید بایند شوند ،مولفه های معماری به شما در مدیریت چرخه حیات کنترلرهای UI کمک می کند بدین معنا که درصورت بروز هرگونه تغییر در داده تمامی مولفه های وابسته را مطلع می کنند.در ادامه ما نحوه استفاده از مولفه های معماری اندروید برای قوی تر کردن استفاده از دیتا بایندینگ را آموزش می دهیم.
شما می توانید از LiveData به عنوان منبع اتصال داده استفاده کنید تا به صورت اتوماتیک UI را جهت به روز شدن داده مطلع سازد.برخلاف object هایی که از نوع Observable بودند (مانند Observable fields) ، object های ازنوع LiveData از چرخه حیات یا lifecycle مطلع اند یا به عبارتی Lifecycle aware هستند.
درصورت متوقف شدن اکتیوتی به هر دلیلی ،در حالی که object درحال انجام پروسه ای باشد ،برنامه کرش نخواهد کرد زیرا lifecycler aware است.
از مزایای دیگر LiveData می توان به موارد زیر اشاره کرد:
در اندروید استودیو 3.1 به بالا شما می توانید از LiveData در کدهای بایندینگ خود بجای Observable استفاده کنید.
همچنین بخوانید: کار با اشیاء داده observable در دیتا بایندینگ
برای استفاده از LiveData با کلاس بایندینگ ،شما باید یک lifecycle owner برای محدوده مورد نظر خود مشخص کنید.برای مثال در نمونه زیر ما اکتیویتی که مجهز به دیتا بایندینگ است را به عنوان lifecycle owner مشخص کردیم.که این کار دقیقا بعد از بایند کردن لایه ،انجام می شود.
جاوا
class ViewModelActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// Inflate view and obtain an instance of the binding class.
UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user);
// Specify the current activity as the lifecycle owner.
binding.setLifecycleOwner(this);
}
}
کاتلین
class ViewModelActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Inflate view and obtain an instance of the binding class.
val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user)
// Specify the current activity as the lifecycle owner.
binding.setLifecycleOwner(this)
}
}
شما می توانید از مولفه معماری اندروید ViewModel (برای اطلاعات بیشتر درباره استفاده از ViewModel برای مدیرید داده های مربوط به UI این مقاله از اندروید را مطالعه کنید) برای بایند کردن داده ها به لایه استفاده کنید.در مولفه ViewModel شما می توانید از LiveDatat ها برای تبدیل یا ادغام داده ها استفاده کنید.در نمونه زیر نمایش دادیم که چگونه داده هارا در ViewModel تبدیل می کنم.
جاوا
class ScheduleViewModel extends ViewModel {
LiveData username;
public ScheduleViewModel() {
String result = Repository.userName;
userName = Transformations.map(result, result -> result.value);
}
}
کاتلین
class ScheduleViewModel : ViewModel() {
val userName: LiveData
init {
val result = Repository.userName
userName = Transformations.map(result) { result -> result.value }
}
}
کتابخانه دیتا بایندینگ کاملا با مولفه های ViewModel کار می کند وسازگار است بدین صورت که تمامی داده هایی که لایه استفاده می کند و در مقابل تغییرشان واکنش نشان می دهد را ارائه می دهد.استفاده از مولفه های ViewModel به همراه کتابخانه دیتا بایندینگ به شما این امکان را می دهد که منطق UI را به خارج از لایه منتقل کنید و به مولفه ها بدهید که این کار تست را برای شما راحتتر می کند.درواقع کتابخانه دیتا بایندینگ اطمینان حاصل می کند که تمامی view ها به منبع داده متصل هستند یا نیستند و تنها مرحله ای که می ماند این است که ما داده درستی را به سمت UI هدایت کنیم !
برای استفاده از مولفه ViewModel با دیتا بایندینگ شما باید یک نمونه (instance) از کلاسی که از ViewModel ارث بری می کند را ایجاد کنید و سپس نمونه خود را به پراپرتی درون کلاس بایندینگ اختصاص دهید
جاوا
class ViewModelActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// Obtain the ViewModel component.
UserModel userModel = new ViewModelProvider(this).get(UserModel.class);
// Inflate view and obtain an instance of the binding class.
UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user);
// Assign the component to a property in the binding class.
binding.viewmodel = userModel;
}
}
کاتلین
class ViewModelActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Obtain the ViewModel component.
val userModel: UserModel by viewModels()
// Inflate view and obtain an instance of the binding class.
val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user)
// Assign the component to a property in the binding class.
binding.viewmodel = userModel
}
}
حال درون لایه می توانید با استفاده از viewmodel ی که الان مقدار محتوی مورد نظر ما را دارد (همان کلاسی که از ViewModel ارث بری میک رد) به متد ها و متغیر های درون کلاس ViewModel خود دسترسی پیدا کنید و با استفاده از دستورات دیتا بایندینگ ،از آنها استفاده کنید.
<CheckBox
android:id="@+id/rememberMeCheckBox"
android:checked="@{viewmodel.rememberMe}"
android:onCheckedChanged="@{() -> viewmodel.rememberMeChanged()}" />
شما می توانید از مولفه معماری اندروید ViewModel ی استفاده کنید که Observable را (جهت اطلاع به بقیه کامپوننت ها زمان تغییر دیتا) پیاده کرده باشد ،دقیقا مشابه زمانی که از LiveData استفاده می کردید.ممکن است موقعیت هایی پیش آید که شما ترجیح دهید که ViewModel از Observable به جای LiveData برای مدیریت داده ها استفاده کند حتی اگر شما مدیریت چرخه حیات اکتیوتی یا lifecycle aware را که با LiveData سازگار بود از دست بدهید.استفاده از مولفه معماری اندروید ViewModel ی که Observable را پیاده کرده باشد به شما کنترل بیشتری برروی binding adapter های درون اپلیکشین را می دهد.
همچنین بخوانید: آموزش آداپتور های بایندینگ (Binding adapters)
برای پیاده سازی کامپوننت observable ViewModel شما باید یک کلاس که از ViewModel ارث بری می کند ایجاد کرده و interface مربوط به Observable را درون آن پیاده کنید.شما همچنین میتوانید منطق سفارشی خودتان را برای زمان هایی که observer یا مشاهده کننده شما subscribe یا unsubscribe می شود ،درون رویداد addOnPropertyChangedCallback() پیاده کنید چرا که زمان subscribe یا unsubscribe شدن یک نظاره گر این رویداد فراخوانی می شود.
مثال زیر یک ViewModel که Observable را پیاده کرده را نمایش می دهد:
جاوا
* A ViewModel that is also an Observable,
* to be used with the Data Binding Library.
*/
class ObservableViewModel extends ViewModel implements Observable {
private PropertyChangeRegistry callbacks = new PropertyChangeRegistry();
@Override
protected void addOnPropertyChangedCallback(
Observable.OnPropertyChangedCallback callback) {
callbacks.add(callback);
}
@Override
protected void removeOnPropertyChangedCallback(
Observable.OnPropertyChangedCallback callback) {
callbacks.remove(callback);
}
/**
* Notifies observers that all properties of this instance have changed.
*/
void notifyChange() {
callbacks.notifyCallbacks(this, 0, null);
}
/**
* Notifies observers that a specific property has changed. The getter for the
* property that changes should be marked with the @Bindable annotation to
* generate a field in the BR class to be used as the fieldId parameter.
*
* @param fieldId The generated BR id for the Bindable field.
*/
void notifyPropertyChanged(int fieldId) {
callbacks.notifyCallbacks(this, fieldId, null);
}
}
کاتلین
* A ViewModel that is also an Observable,
* to be used with the Data Binding Library.
*/
open class ObservableViewModel : ViewModel(), Observable {
private val callbacks: PropertyChangeRegistry = PropertyChangeRegistry()
override fun addOnPropertyChangedCallback(
callback: Observable.OnPropertyChangedCallback) {
callbacks.add(callback)
}
override fun removeOnPropertyChangedCallback(
callback: Observable.OnPropertyChangedCallback) {
callbacks.remove(callback)
}
/**
* Notifies observers that all properties of this instance have changed.
*/
fun notifyChange() {
callbacks.notifyCallbacks(this, 0, null)
}
/**
* Notifies observers that a specific property has changed. The getter for the
* property that changes should be marked with the @Bindable annotation to
* generate a field in the BR class to be used as the fieldId parameter.
*
* @param fieldId The generated BR id for the Bindable field.
*/
fun notifyPropertyChanged(fieldId: Int) {
callbacks.notifyCallbacks(this, fieldId, null)
}
}
امیدوارم این آموزش برای شما مفید بوده باشد…