۲۳ شهریور، ۱۴۰۰
نویسنده @mahdiabbasian یک مقاله تازه به اسم معرفی معماری MVI بخش دوم نوشت.
بعد از مدت ها مشغله در کار و زندگی برگشتم با ادامه معماری MVI
در خدمت دوستان پارس کلیکی هستم
در بخش اول معرفی کوتاهی از بخش های مختلف این معماری داشتم و به صورت کوتاه اشاراتی داشتیم در این بخش قصد دارم پیاده سازی این معماری رو بهتون آموزش بدم:
لایه Model
در دیگر معماری ها Models
به دید یک لایه نگهدارنده دیتا نگاه شده است در واقع Back کار بودند به مانند ارتباط دهنده API
و دیتابیس، در معماری MVI
علاوه بر این با ساخت یوآی به صورت state
مواجه هستیم که دایمی هستند به طور مثال اگر مادل را به صورت یک دیتا کلاسی از Movie
در نظر بگیریم:
data class Movie (
var id: Long? = null,
var countryProduct: String? = null,
var rateImdb: String? = null,
var categoryName: String? = null,
var director: String? = null,
)
یکی از قابلیت های خیلی خوب که خیلی ازش استفاده میکنم استفاده از sealed class
ها در تعریف state
های مختلف هست برای نمونه در اینجا با توجه به دیتا کلاسی از Movie
داریم چند حالت در DataState
خود داریم:
sealed class MovieState {
object LoadingState : MovieState()
data class DataState(val data: List<Movie>) : MovieState()
data class ErrorState(val data: String) : MovieState()
}
Views and Intents
مانند معماری MVP
معماری MVI
برای ویو یک interface
در نظر می گیرد:
interface MainView {
fun displayMoviesIntent()
fun render(state: MovieState)
}
که توسط اکتیویتی یا فرگمنت implement
می شود در واقع می توان گفت که ویو در MVI
تمایل داره از intent
استفاده کنه که به اکشن کاربر پاسخ بده در نهایت بر طبق state
ها و اینترفیس حالت ها در اکتیویتی به شکل زیر خواهد بود:
class MainActivity : MainView {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
//implement interface
override fun displayMoviesIntent() = button.clicks()
//implement interface
override fun render(state: MovieState) {
when(state) {
is MovieState.DataState -> renderDataState(state)
is MovieState.LoadingState -> renderLoadingState()
is MovieState.ErrorState -> renderErrorState(state)
}
private fun renderDataState(dataState: MovieState.DataState) {
//Render movie list
}
private fun renderLoadingState() {
//Render progress bar on screen
}
private fun renderErrorState(errorState: MovieState.ErrorState) {
//Display error mesage
}
}
این آموزش ساده ای از معماری MVI
بود تمامی موارد بالا براساس تلفیق با معماری دیگر مانند MVVM
و Clean
متفاوت خواهد بود به دلیل اینکه در این معماری ها لایه های مختلفی قرار داره اما اصل معماری به همین سادگی هستش.
۴ اسفند، ۱۳۹۹
نویسنده @mahdiabbasian یک مقاله تازه به اسم معرفی معماری MVI بخش اول نوشت.
ضرورت توسعه این معماری
همانطور که می دانیم معماری ها در جهت هر چه بهتر سازماندهی کردن کدها و جهت نگهداری هر چه بهتر در زمان توسعه به وجود آمدند در این میان معماری جدید MVI
با استفاده از Reactive Programming
راهکار تازه ای ارایه کرده است، این معماری در اصل یک معماری برای Cycle.js
در جاوا اسکریپت است که در اندروید هم پیاده سازی شده است همچنین در این معماری امکان استفاده از Rxjava
و LiveData
وجود دارد.
کلمات در این معماری مخفف Model-View-Intent
هستند و اساس آن بر پایه Intent
است این لایه نشان دهنده قصد یا تمایلی برای انجام عملی از طرف کاربر است یه این معنا که این لایه یک ویو دریافت می کند و میتواند Model
را به حالت جدیدی ترجمه کند.
لایه Model
این لایه کار نگهداری پایگاه های داده، تمامی داده های مربوط به API
ها پ غیره را برعهده دارد، همچنین در این معماری کار این لایه کمی متفاوت است به این صورت که خروجی از Intent
میگیرد و بنا به حالت (State
) که لازم است آن را برای کاربر نهایی تغییر میدهد.
لایه View
در نهایت در این لایه State
های جدید باعث ایجاد تغییرات در View
خواهند شد و نتیجه نهایی به کاربر نشان داده خواهد شد.
۱۰ بهمن، ۱۳۹۹
@mahdiabbasian به گفتگوی استاندارد داکیومنت نویسی برای یک اپ جواب داد.
منم با نظر آقای امین موافق هستم و اینکه به نظر من باید دید که سطح اون مشاغل چطور هس اما چیزی که در بیشتر موارد اتفاق میوفته اینه که داکیومنت رو نمیخونن تا جایی که لازمشون نباشه اصلا چرا راه دور بریم یه جورایی خودمون هم همینطور هستیم چون باید نیاز ببینن تا برن سراغش در مورد دیزاین پترن ها به شدت موافقم چون این هاس که کد رو کلین نگه میداره و بهتر میکنه کار رو و اینکه کارفرماها هم به دولوپری که دیزاین پترن استفاده کرده باشه البته اگر فقط فهم مدیریتی نداشته باشه بیشتر بها میده ولی خب در نهایت بخام بگم اینجور کارها خیلی خوبه اما نه خیلی در ایران! البته استثنا هم وجود داره
۸ بهمن، ۱۳۹۹
نویسنده @mahdiabbasian یک مقاله تازه به اسم پیاده سازی viewBinding به زبان ساده نوشت.
همانطور که احتمالا در جریان هستید یکی از مشکلات و دردسرهای دولوپرهای اندروید سر و کله زدن با خطایی به نام null pointer exception
است در اصل ویو بایندینگ جهت هر چه کمتر کردن این خطا که همگی ما حداقل یکبار با آن روبه رو شده ایم توسط گوگل در جت پک قرار گرفت با استفاده از این روش خصوصا در معماری MVVM
میتوانیم با پدیده پرتکراری به نام findViewById
در اپلیکیشن ها خداحافظی کنیم!
پیاده سازی ویوبایندینگ
برای فعال سازی این قابلیت کافیست در فایل build.gradle
کد زیر را اضافه کنیم:
viewBinding{
enabled = true
}
کارکرد این قابلیت به صورتی است که برای لایه های موجود در اپلیکیشن کلاسی معادل با آن میسازد که در هر جایی قابل استفاده است در اصل لایه توسط نرم افزار bind
می شود
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding mainBinding =
ActivityMainBinding.inflate(getLayoutInflater());
setContentView(mainBinding.getRoot());
}
}
همانطور که ملاحظه میکنید نمونه ای از لایه activity_main.xml
ایجاد کردیم که توسط اون میتونیم به هر آی دی متصل بشیم و در اینجا نیازی به findViewById
نیست همچنین در این کلاس متدی استاتیک به نام getRoot
وجود دارد که روت لایه را برمیگرداند اگر به طور نمونه در این لایه یک تکست ویو داشته باشیم به کد زیر:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textViewMain"/>
</RelativeLayout>
در زمان پیاده سازی آن در اکتیویتی خواهیم داشت:
mainBinding.textViewMain.setText("ParsClick");
و در فرگمنت ها خواهیم داشت:
@Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
mainbinding = FragmentMainBinding.inflate(inflater, container, false);
View view = mainbinding.getRoot();
return view;
}
به همین سادگی!
۲۳ دی، ۱۳۹۹
نویسنده @mahdiabbasian یک مقاله تازه به اسم معرفی معماری MVVM نوشت.
ضرورت ایجاد معماری MVVM
همانطور که میدانید در پروژههای تجاری بزرگ آنچه بیش از هر چیز اهمیت دارد انعطاف پذیری در زمان توسعه است به طوری که تیم بتوانند به خوبی با یکدیگر کار کنند ایجاد این معماری توسط جان گوسمن و معرفی آن در جت پک گوگل پاسخی به بهبود هر چه بیشتر این نیاز بود.
می توان گفت پایه اصلی این معماری جداسازی منطق از لی اوت و استایل اپلیکیشن است به طوری که در تیم فردی می تواند روی استایل برنامه کارکند و همزمان فرد دیگر تیم منطق ان را پیاده سازی کند این حالت در نهایت به خوانایی هر چه بیشتر کد و انعطاف پذیری کل پروژه منجر خواهد شد.
حروف MVVM
مخففModel، View، ViewModel
هستند.
لایه Model
این لایه شامل تمامی موارد مرتبط با داده مانند Api
ها، کلاس ها مانند Entitiy
ها ، فایربیس و ... هست اما در این لایه شرایطی حاکم است به این مفهوم که این لایه از view
و viewmodel
بی اطلاع است یعنی استقلالی برای خود دارد.
لایه view
اکتیویتیها، فرگمنتها، لایههای ایکس ام ال همگی در این لایه قرار می گیرند نکته ای که در اینجا مهم است اینجاست که این لایه تمامی موارد لازم را به viewmodel
ارسال می کند اما به طرز جذابی پاسخ را به طور مستقیم دریافت نمیکند همچنین این لایه می تواند تحت شرایطی که لازم باشد از viewmodel
درخواست کند که پردازشی را صورت دهد و model
را براساس آن بروزرسانی کند.
لایه viewmodel
این لایه واسطی بین دو لایه دیگر است کارکرد این لایه به این شکل است که داده های مورد نیاز را از model
دریافت میکند و به view
تحویل میدهد از جمله موارد مهم که در این لایه انجام میشود می توان به عملیات بایندینگ دیتا اشاره کرد اما از جمله نکات مهم در این لایه این است که وظایف inflate
لایه ها و استارت اکتیویتیها به عهده این لایه نیست و باید از ان اجتناب کرد.
در حال حاضر از دو روش viewBinding
و Rxjava
برای پیاده سازی این معماری استفاده می شود به طور خلاصه در viewBinding
تمامی لایه ایکس ام ال تحت یک کلاس در اکتیویتی و فرگمنت قرار میگیرد و تمامی عملیاتهای لازم تحت این کلاس صورت میپذیرد همچنین در RXjava
تمامی محتوای قابل نمایش تحت یک ترد جداگانه به یوزر (Observe
) نمایش داده میشود.