پیاده سازی پترن MVP در اندروید

آموزش اندروید دیزاین پترن ام وی پی mvp design pattern tutorial android source code included آموزش رایگان همراه با سورس کد رایگان پروژه سورس اندروید model view presenter mvc mvvm model view modelview

سطح آموزش: #پیشرفته

قبلا داخل پست‌های وبلاگ و کامنت‌ها راجع به اهمیت داشتن یک پترن مشخص برای توسعه و MVP به عنوان یک پترن پذیرفته شده توی اندروید صحبت کردیم. اما به صورت عملی وارد کد نشدیم.

توی این پست قصد داریم در قالب یک پروژه کامل مدلی از mvp رو با هم پیاده کنیم. اگر آشنایی به بحث ندارید شاید بد نباشه از اینجا شروع کنید و بعد سری به این پست بزنید.

توجه مهم

وقتی راجع به پترن‌هایی مثل mvp صحبت می‌کنیم باید توجه داشته باشید که فقط یک روش برای حل مسئله وجود نداره. هر برنامه‌نویسی بسته به نیاز خودش ممکنه تغییراتی روی شیوه نوشتن کدها بده. هدف نهایی اینه که به کدی قابل توسعه و قابل تست برسیم، حالا اینکه دقیقا چطور به این هدف می‌رسیم مرحله دوم اهمیت رو داره.

بنابراین اگر جایی مدل دیگه‌ای از mvp (یا هر پترنی) رو دیدید که با اونچه که قبلا یاد گرفته بود فرق داشت، تصور نکنید یکی از این دو روش غلط بوده. اینطور تصور کنید که یک مسئله داریم که mvp پاسخِ اون مسئله‌ست. حالا هرکسی این پاسخ رو با ادبیات مخصوص به خودش می‌نویسه. و احتمالا هرکودوم از رویکردها مزایا و معایبی دارن.

درباره کد

برای این آموزش من یک پروژه note آماده کردم که با mvp پیاده سازی شده. آموزش هم بر اساس همین پروژه پیش میره.

تعریف پروژه به این شکل هست که کاربر توی اکتیویتی اول میتونه یکسری فولدر بسازه. سپس داخل هر فولدر میتونه انواعی note رو بسازه. برای این کار از یک دیتابیس sqlite با دو تا table استفاده کردم یکی برای فولدرها و دیگری برای فایل‌ها. رابطه folder به file هم از نوع one to many هست و یک فولدر میتونه هر تعدادی فایل داشته باشه در حالیکه هر note فقط میتونه داخل یک فولدر قرار بگیره.

برای ارتباط با دیتابیس از ContentProvider و برای دریافت اطلاعات از Loader استفاده شده. همچنین برای نمایش اطلاعات با وجود اینکه نیازی نبود از فرگمنت استفاده کردم. دلیل این بود که میخواستم پروژه از تمام تکنولوژی‌های مرسوم اندروید استفاده کرده باشه.

همچنین این پروژه بدون استفاده از هیچ کتابخونه‌ای نوشته شده. در آینده آموزش دیگه‌‌ای خواهم گذاشت که به طور سنگین با استفاده از تمام کتابخونه‌های معروف مثل Dagger و RxJava و… نوشته شده باشه.

در مورد شیء گرایی از SOLID استفاده شده. همچنین از اکثر دیزاین پترن‌هایی که تا امروز یاد گرفتیم مثل dependency injection و Iterator و Singleton و… به طور گسترده استفاده شده.

داکیومنت اپلیکیشن هم خیلی کامل هست. سعی کردم برای تمام متد‌ها، interfaceها و کلاس‌ها تا کامنت گذاری استاندارد انجام بدم تا هم کار کردن با کد براتون ساده‌تر بشه و هم آموزشی برای کامنت گذاشتن باشه.

در نهایت اینکه پروژه رو بصورت افزایشی توسعه دادم و از امکانات git در این مورد استفاده کردم که میتونه مرجعی برای commit کردن و توسعه incremental باشه.

 سورس پروژه رو میتونید روی گیت‌هاب پیدا کنید.

نقطه شروع

شروع هر اپلیکیشن معمولا یک activity هست پس ما هم از همینجا شروع می‌کنیم.

View همان Activity نیست!

البته قبل از اون لازم میدونم یک توضیحی بدم. توی مدلی که من از mvp ارائه می‌کنم ما اکتیویتی رو از view جدا می‌کنیم.

روشی که عموما می‌بینیم این هست که معمولا کدهای مربوط به view رو داخل activity می‌نویسن. از findViewById ها گرفته تا تعریف listener و…

این روش یک ایراد بزرگ داره، میدونیم که activity فرزند کلاس context هست و بسیاری از وظایف اپلیکیشن اندرویدی بر دوش context هست. وجود این وظایف باعث میشه ما نتونیم logic رو از activity جدا کنیم و همیشه ناچار هستیم بخشی از عملیات اپلیکیشن رو به شکلی وارد اکتیویتی کنیم.

اما طبق اصول solid میدونیم که نباید یک کلاس بیش از یک وظیفه به عهده داشته باشه. ضمن اینکه در نهایت هدف ما جدا سازی کامل view از model هست و مدل نمیتونه بدونه یک instance از activity برخی فعالیت‌ها مثل اجرای intent رو انجام بده. بنابراین اگر view داخل اکتیویتی باشه باعث میشه مدل هم به view دسترسی داشته باشه که به طور کل با اصول mvp منافات داره.

در نهایت مهمترین دلیل این هست که من دوست دارم اپلیکیشنم modular باشه. به این معنی که این viewـی که الان نوشتم رو بتونم بعدا با یک back-end دیگه هم استفاده کنم بدون اینکه نیاز داشته باشم تغییر خاصی توی view بدم. و یا برعکس بتونم بدون تغییر model و presenter بتونم view رو عوض کنم. در صورتی که view همون activity باشه این کار عملا غیر ممکن خواهد بود.

اولین activity

اولین اکتیویتی البته MainActivity هست اما بهتره اول از NoteActivity شروع کنیم:

کد

همونطور که می‌بینید کلاس اکتیویتی بی‌نهایت خلوت و ساده‌ست. تنها وظیفه اکتیویتی من تعریف model – view و presenter هست و باقی عملیات و کارها داخل این کلاس‌ها انجام میشه.

ما ابتدا view و model رو initialize می‌کنیم و سپس اون‌ها رو به presenter پاس می‌دیم.

توجه کنید راه ارتباطی activity با کلاس‌های دیگه از طریق callback هست. اگر با callback آشنایی ندارید به این آموزش مراجعه کنید.

اینکه activity چه لایه‌ای رو نمایش بده داخل اکتیویتی مشخص نمیشه بلکه view وظیفه تصمیم گیری در این خصوص رو داره.

کلاس NoteView

توصیح

توی constructor کلاس view تصمیم می‌گیریم که قصد داریم چه layoutـی رو نمایش بدیم و بر اساس اون view رو پیاده سازی می‌کنیم.

به شخصه طرفدار findViewByIdها نیستم ولی از اونجایی که هدف عدم استفاده از کتابخونه خارجی بود از ButterKnife استفاده نکردم. البته با استفاده از Java Reflection هم میشه کاری کرد که نیازی به نوشتن findViewها نباشه ولی استفاده زیاد از reflection روی عملکرد اپلیکیشن تاثیر خوبی نمیذاره چرا که reflection در زمان runtime کدهایی رو generate می‌کنه.

مسئله بعدی که باید توجه کنید وجود متد setPresenter داخل view هست. طبق مدل mvp میدونیم که model و view نباید ارتباط مستقیم با همدیگه داشته باشن و پل ارتباطی‌شون presenter هست، به همین دلیل ما از این متد استفاده می‌کنیم. توجه کنید که متد setPresenter رو فقط از داخل presenter صدا کنید و حتما حواستون باشه هرجا که از view – model یا presenter استفاده می‌کنید حتما همون instanceـی باشه که در اکتیویتی ساختیم.

در پروژه بعدی می‌بینیم که dagger با استفاده از scope مسئله singleton رو حل می‌کنه اما ما باید خودمون حواسمون رو جمع کنیم.

داخل view یک enum هم داریم که نوع note رو مشخص می‌کنه. توی پروژه ما میتونیم هم نقاشی بکشیم و هم text ذخیره کنیم. اینکه note مورد نظرمون از چه نوعی هست رو با این enum مشخص می‌کنیم.

در نهایت هم یک interface به اسم OnNewNoteRequestListener داریم که وقتی کاربر تصمیم به ساخت note گرفت داخل OnClickListenerـی که ساختیم ازشون استفاده می‌کنیم.

کلاس NoteModel

متدها تا حد زیادی خودشون رو توضیح میدن. در درجه اول با استفاده از DI اکتیویتی رو به کلاس مدل پاس می‌دیم. توجه کنید که intent از جنس data هست و حتما باید داخل کلاس model قرار بگیره. به خصوص که ما در intent برای جابجایی دیتا بین اکتیویتی‌ها استفاده می‌کنیم.

کاربر با انتخاب نوع noteـی که میخواد به view میگه کودوم callback صدا بشه. سپس داخل presenter ما interface رو implement می‌کنیم و اونجا به مدل میگیم که بسته به درخواست یکی از دو متد newTextNoteRequest یا newDrawingNoteRequest رو صدا بزنه.

متد دیگه‌ای هم داریم به اسم editNoteRequest که مربوط به وقتی میشه که کاربر قصد edit کردن noteـی که قبلا نوشته رو داره. این متد از طریق recyclerviewـی که noteها رو نمایش میده صدا میشه و با set کردن یک سری flag به اکتیویتی note میگه در حال edit کردن note هست.

کلاس presenter

کلاس presenter همونطور که می‌بینید بین model و view ارتباط برقرار می‌کنه. همچنین دو تا متد onCreate و onDestroy داریم. تمام منطقی که نیاز داشته باشیم داخل life cycle اکتیویتی اتفاق بیفته داخل presenter و در متدهایی این چنینی می‌نویسیم.

 

حالا که با ساختار کلی هر اکتیویتی آشنا شدیم به بررسی بعضی از پکیج‌ها میپردازیم.

View Package

داخل این پکیج ۵ بخش داریم:

adapter

adapter ها ساب کلاس‌هایی از RecyclerView Adapter هستن.

custom

viewهای custom که برای اپلیکیشن طراحی می‌کنم رو داخل این پکیج قرار میدم. توجه کنید که custom viewها از جنس view هستن و نباید logic داشته باشن. اگر نیاز هست منطقی رو داخل custom view انجام بدید بایستی با استفاده از interface به model یا presenterـی که کلاس در اون اجرا میشه ارجاع بدید.

dialog

دیالوگ‌ها از جنس دیالوگ فرگمنت هستن و من اون‌ها رو داخل presenter دسته بندی می‌کنم. شاید این سوال پیش بیاد حالا که دیالوگ از جنس فرگمنت هست چرا برای اون presenter جدا در نظر نمی‌گیریم. دلیلش این هست که هدف ما از mvp در نهایت راحت‌تر شدن برنامه‌نویسیه و اینکه برای تک‌تک کلاس‌ها این جداسازی رو انجام بدیم فقط کار رو پیچیده‌تر میکنه. بخصوص که هیچ یک از فواید داشتن presenter و model مثل modular شدن کد رو برای دیالوگ نداریم.

list

لیست‌ها فرگمنت‌هایی هستن که داخلشون یک recycler view دارن. در حالت عادی ما باید جای استفاده از fragment در اکتیویتی یک RecyclerView میذاشتیم و لیست رو نمایش می‌دادیم. دلیل اینکه من از فرگمنت استفاده کردم این بود که میخواستم این مدل کد زدن رو هم داخل اپلیکیشن داشته باشم. در پروژه بعدی که کتابخونه‌ها هم اضافه میشه به جای فرگمنتی که لیست داره خیلی ساده‌تر فقط از یک لیست استفاده کرده‌ام.

Component Package

به طور کلی من طرفدار استفاده از Fragment داخل اپلیکیشن نیستم. دلیل عمده بوجود اومدن فرگمنت‌ها modular کردن اپلیکیشن و همچنین نمایش صحیح در اسکرین‌های مختلف بوده و معتقدم تا حد ممکن بهتره ازشون استفاده نشه. ضمن اینکه اگه درست handle نشه میتونه در پروژه‌های سنگین‌تر پرفورمنس اپلیکیشن رو کاهش بده.

 

کلاس‌های داخل component شامل interfaceهایی هست که یک فرگمنت باید پیاده سازی کنه.

برای مثال کلاس NotesComponent رو ببینید:

متدهای view و presenter داخل component تعریف می‌کنیم.

سپس داخل کلاس لیستمون component.view و داخل کلاس پرزنترمون component.presenter رو implement می‌کنیم و کدها رو وارد می‌کنیم. توجه کنید که لزومی به استفاده از component و لیست‌هایی داخل فرگمنت نیست و من برای اینکه کد کامل و شاملی نوشته باشم به این شکل استفاده کردم. بنابراین اگر باعث سردرگمی‌تون شده می‌تونید از بخش component و فرگمنت‌ها عبور کنید.

Util Package

کلاس‌هایی که یک خدمت به خصوصی رو به ما میدن رو داخل این پکیج میذاریم.

مثلا کلاس FileUtil متدهایی برای کار با فایل در اختیارمون میذاره. متد PremissionHandler رو هم قبلا باهاش برخورد داشتیم.

مشخصه که کلاس‌های این متد باید به طور مستقل از کل اپلیکیشن باشن و به همین دلیل هم پکیج مجزایی دارن.

Model Package

زاجع به model در mvp مفصل صحبت کردیم. اما به طور کلی هرچیزی از جنس دیتا رو باید به عنوان model دسته بندی کرد. برای همین هم model چند زیر پکیج داره.

در درجه اول کلاس‌هایی هستن که مستقیما داخل پکیج هستن که همون مدل‌های mvp هستن که آشنا شدیم باهاشون.

بعدی db هست که وظیفه مدیریت انواع ارتباطات با دیتابیس رو داره. کلاس‌های این پکیج با استفاده از تمام ابزارهای کارآمد اندروید من جمله ContentProvider و ContentResolver و SQLiteOpenHelper با دیتابیس ارتباط برقرار میکنن و عملیات ما رو انجام میدن.

پکیج بعدی structures هست که شامل تمام ساختارهایی هست که داخل اپلیکیشن وجود دارن. برای مثال POJO ها در این پکیج قرار میگیرن.

 

نتیجه

فکر می‌کنم تا حد خوبی با پروژه و مدل mvp آشنا شده باشید اما تنها روش برای مسلط شدن اینه که پروژه رو دانلود کنید و خودتون دست به کد بشید و سعی کنید امکاناتی رو به پروژه اضافه کنید و pull request بفرستید. اگر کارتون از نظر پترن ایرادی داشت با همدیگه راجع بهش صحبت می‌کنیم و اگر مشکلی نداشت هم به پروژه اضافه می‌شه.

برای مشاهده پروژه به اینجا مراجعه کنید.

 

 

 

37 دیدگاه برای “پیاده سازی پترن MVP در اندروید

  1. سلام خسته نباشید
    خیلی عالی بود.
    انشاالله در آموزش های بعدی نحوه پیاده سازی ارتباط با سرور رو به کمک کتابخانه های نظیر retrofit رو توی معماری mvp رو بیان کنید.
    چون اکثر sample های که توی اینترنت وجود داره با retrofit بیان شده.

  2. سلام و خسته نباشید واقن کیف کردم از سایتت ایشالا ک موفق باشید
    ببخشید ی سوال :
    در صورتی ک ی اپ داشته باشیم با دانلود زیاد و انلاین بدلیل ریکوست های فراوان ب سمت سرور و جوابهای برگشتی نطرتون درباره نحوه اتصال ب چ شکلی هست
    رتروفیت ..والی…دست ساز (httpurlconnection ) نطر شما کدوما هست؟

      1. سلام ، نظرتون درباره استفاده از volly چیه ؟ اون برای استفاده از تصویر هم امکانات گذاشته و اینکه قابل فهم تر نسبت به رترفیته فک میکنم ، اما من هنوز تازه کارم ، میخواستم نظرتون رو بدونم ، تو اکثر سایت ها میگن رترفیت خیلی بهتره و امتیاز بیشتری هم نسبت به والی داره اما من تو یه سایت انگلیسی که مقایسه کرده بود دیدم به والی رسید و اینکه والی کتابخانه خود گوگله و حتما در آینده بیشتر بهش میرسه ، بهتر نیست از همین الان با این بیشتر کار کنیم ؟
        ممنون

        1. سلام. من شخصا retrofit رو ترجیح میدم. گوگل معمولا به هرچیزی اومده برسه خرابترش کرده حالا اگه هم در آینده volly خیلی بهتر شد میشه خیلی راحت سوئیچ کرد. به نظرم الان با retrofit کار کنی بهتره.

  3. سلام ، کلا سایت خوبی دارید و خیلی خوب موضوعات پیچیده مثل dagger رو توضیح میدید اما در مورد پیاده سازی mvp من مقالاتی که خوندم تقریبا همشون میگفتن که activity یا fragment نقش view رو داره و برای اینکه داخل acitvity دیگه نیایم presenter و model رو بسازیم و رفرنسهاشون رو به هم بدیم از di استفاده میکنیم ، اما با این مدل پیاده سازی که شما انجام دادید اصلا activity هیچ کاره میشه این وسط البته شاید برای اینکه خوانایی برنامه بره بالا اینکارو میکنید اما کار اضافه هست به نظرم وقتی که میشه همه اینکارها رو داخل activity انجام داد .

    1. وقتی اکتیویتی رو به عنوان view استفاده می‌کنیم تست کردن خیلی سخت میشه. هدف ما از تمام این پترن‌ها اینه که در نهایت بتونیم تا حد ممکن بخش‌های مختلف اپلیکیشن رو طوری بنویسیم که وابستگی‌ای به همدیگه نداشته باشن. در صورتی که ذات اکتیویتی طوری هست که model هم بهش نیاز داره. برای همین اگه اکتیویتی رو به عنوان view بگیریم، مدل و view به هم وابستگی خواهند داشت و اینطوری کل فلسفه استفاده از دیزاین پترن زیر سوال میره.

      1. آخرین دلیلی که نوشتید برای این نوع پیاده سازی ، منطقی هست ولی اینکه منطق برنامه با اکتیویتی قاطی میشه رو من جایی ندیدم و اون interface contract هایی که مینویسیم برای اینه که پرزنتر فقط در حد اون contract به ویو دسترسی داشته باشه و نه بیشتر از اون ، قطعا منطقی نیست که پرزنتر به همه ی متدهای اکتیویتی دسترسی داشته باشه ، حداقل تو مقالات معتبری که من خوندم این چیزها رعایت شده بود ، اما این روش پیاده سازی شما قطعا مفیده و نگهداری و تغییر کدها قطعا راحت هست و اونقدر خوانایی پروژه رو پایین نمیاره

    1. سلام. view اکتیویتی رو داره. دلیلش اینه که خیلی از کارهایی که view میخواد انجام بده نیاز به context داره. مثلا یه دیالوگ بخوایم نشون بدیم به context نیاز داریم و خیلی کارهای دیگه. نکته مهم اینه که presenter نباید اکتیویتی رو ببینه.

      1. خب توی همین مقاله گفتید که :
        “View همان Activity نیست!
        البته قبل از اون لازم میدونم یک توضیحی بدم. توی مدلی که من از mvp ارائه می‌کنم ما اکتیویتی رو از view جدا می‌کنیم”

        1. آره دیگه. اگه اکتیویتی همون view بود که دیگه کلاس جدا نداشت. جدا میکنیم که کدِ modular تری داشته باشیم و تست و توسعه ساده‌تر بشه. اما چون context یک god object هست که خیلی از کارها توی android بهش وابسته‌ست ناچاریم یک instance از activity رو به view پاس بدیم که کارهایی که نیاز به context دارن رو بتونیم انجام بدیم.
          در واقع میشه گفت view و activity رو جدا می‌کنیم و تنها یک instance از activity رو داخل view داریم.

  4. یه سوال دیگه
    چرا اینترفیس ها رو توی کلاس ها تعریف میکنید؟ اگر یک پوشه جدا برای اینترفبس ها درست کنیم و همشون رو یک جا بذاریم بهتر نیست ؟

    1. این interfaceها رو میخوایم صرفا داخل این کلاس ازشون استفاده کنیم برای همین نیازی نیست کلاس جدایی براشون بسازیم. نه اینکه نتونیم ولی لزومی هم نداره. بعد اینکه یک کلاس داشته باشیم و همه اینترفیس‌ها اونجا باشه خوب نیست چون ما میخوایم بعدا interfaceها رو داخل presenterمون implement کنیم و اگه همه داخل یک کلاس باشن نمیتونیم به طور جدا گونه interfaceهای هر view رو داخل presenterـش implement کنیم

  5. سلام خسته نباشید. شما توی این لینک https://github.com/TaherHaghverdi/ReactiveRetrofitTutorial
    که mvp رو با استفاده از retrofit و rxjava پیاده سازی کردین توی قسمت presenter اطلاعات رو از سرور میگیرین. براساس این کدی که نوشتین انگار بجای mvp از vp استفاده کردین. ینی قسمت model رو استفاده نکردین. این اشتباه نیست به نظرتون؟
    البته بگم من درحدی نیستم از کار شما اشکال بگیرم ولی میخوام برام قابل درک بشه

    1. نه حق با شماست علی جان. این پروژه رو به طور کل فراموش کرده بودم. این پروژه ایرادات زیادی داره که قرار بود تکمیلش کنم ولی فراموش کردم. الان اصلا mvp به حساب نمیاد صرفا میخواستم استفاده از retrofit با RxJava رو نشون بدم. برای mvp به این پیاده‌سازی مراجعه کن. ضمنا یک پترن خیلی قوی‌تر هم هست که خودم اخیرا ازش استفاده می‌کنم و به زودی آموزشش رو قرار میدم.

  6. سلام
    یه چند تا سوال دارم
    توی یک برنامه اگر من سرویس داشته باشم.این سرویس رو کجا باید بزارمش؟ من الان میذارمش کنار activityهای دیگه.
    یه سوال دیگه هم که دارم این هستش که لاجیکی که تو این سریس ها قرار هست اجرا بشه رو کجا باید تعریف کرد؟ اصلا سرویس ها میتونن به مدل ها مستقیم دسترسی داشته باشن؟
    ممنون میشم راهنمایی کنید.

  7. سلام
    یه چند تا سوال دارم
    توی یک برنامه اگر من سرویس داشته باشم.این سرویس رو کجا باید بزارمش؟ من الان میذارمش کنار activityهای دیگه.
    یه سوال دیگه هم که دارم این هستش که لاجیکی که تو این سریس ها قرار هست اجرا بشه رو کجا باید تعریف کرد؟ اصلا سرویس ها میتونن به مدل ها مستقیم دسترسی داشته باشن ؟
    ممنون میشم راهنمایی کنید.

    1. به نظرم کنار پکیج‌های دیگه مثل presenter و model یک پکیج هم درست کن به اسم service و کلاس‌های سرویس رو داخل اون بذار. در مورد لاجیک هم سرویس نباید خیلی لاجیک سنگینی داشته باشه برای همین logicش رو هم داخل خودش تعریف می‌کنیم. برای دسترسی به مدل هم اگه لازمه میتونه داشته باشه ولی دسترسی نباید قانون وابستگی رو نقض کنه یعنی می‌تونه از مدل استفاده کنه ولی نباید تغییری روش ایجاد کنه.

  8. یه سوال دیگه هم داشتم
    الان فانکشن هایی که کار های اتصال اینترنت (کارهای دانلود و اتصال به سرور .. که با رتروفیت انجام میدم) همش رو گذاشتم توی یک کلاسی به اسم intenet که توی مسیر model>server>internet.class گذاشتمشون و توی سرویسم میام و از متد های این کلاس intenet استفاده می کنم.
    کار درستی هستش؟
    ممنون

    1. به نظرم پکیج network رو از model جدا کن. کاری که کردی اشتباه نیست ولی یه وابستگی بین کلاس سرویس و internet بوجود اومده که بهتره نباشه. به نظرم خیلی حرفه‌ای‌تر میشه یک سری interface تعریف کنی (اسمشو بذاریم repository) که به ازای هر api call یک متد داشته باشه و بعد یکسری کلاس‌ هم باشه که این repositoryها رو implement کنه. در نهایت با استفاده از dagger بیای و repository رو به سرویس inject کنی.

  9. خیلی ممنون
    یه سوال دیگه هم داشتم که متفاوت هستش.
    توی این برنامه ای که گذاشتید توی قسمت دیتابیسش چرا اینقدر پیچیده هستش؟
    content provider چرا استفاده کردی؟ مگه content provider ها برای اشتراک گذاری داده های یک برنامه با سایر برنامه ها استفاده نمیشه؟ پس چرا اینجا اومده؟
    خیلی ممنون

  10. سلام ممنون بابت اموزش های خوبتون
    یه سوال الان اگه ما توی uiمون مثلا یه دکمه داشته باشیم که روش کلیک میشه و مثلا یه اکتیویتی دیگه باز میشه یا یه toast نمایش داده میشه در کل میخوام بگم که با model کاری نداریم در این دکمه و یه همچین کاری میخواییم بکنیم مثلا گفتم بره به یه اکتیویتی دیگه
    حالا سوالم اینه ایا برای این دکمه ما باید بریم در present انجام بدیم ؟ یعنی اینکه از present یه تابع رو صدا کنیم که اون تابع باز بیاد و یک تابع از view رو صدا کنه که توی اون تابع دستور باز شدن یه اکتیویتی دیگه هست
    یا در این چنین موارد میتونیم به present کاری نداشته باشیم و دستورات بنویسم بدونم صدا زدن present

    1. هر دو صورتش درسته. نظر من اینه که واقعا لازم نیست برای هرکار کوچیکی به پرزنتر رجوع کنیم ولی خب بعضی وقتا با اینکه با مدل کار نداریم کارمون بخش مهمی از لاجیک رو در برداره. مثلا فرض کنید اپلیکیشنمون چندتا state داره و میخوایم با هر کلیک بین این stateها جابجا شیم. بهتره که این از داخل پرزنتر هندل بشه چون لاجیک نرم‌افزارمون رو شامل میشه.

  11. سلام قرار بود یه پروژه با داگر و باقی تاکنولوژی ها بسازید با معماری mvp بد استاد یه سوال الان اکتیوتی یه مدل حساب میشه .اگر اره میشه یه سورس بدید که یه اکتویتی رو از ویو جدا کرده باشن و منو کشوی داسته باشه . اگر حساب نمیشه یه جور ویو میشه حسابش کرد کجای دیاگرام این معماری قرار میگیره

  12. یک سوال ذهنمو درگیر کرده که چرا ما از سه کلاس استفاده می کنیم چون خود کلاس مدل می تونه مستقیم با کلاس view رابطه برقرار کنه چرا presenter را رابط قرار میدیم؟

  13. سوالی که ذهن منو درگیر کرده اینکه ما تو کلاس NoteView یک شی از Presenter داریم. چرا وقتی میخوایم تابع onNewTextNoteRequest رو صدا کنیم یک اینترفیس تو NoteView ساخیتم و اونو تو Presenter ، پیاده سازی کردیم ؟
    چرا مستقیم اون تابع رو صدا نکردیم ؟

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *