يستهدف هذا المقال المبتدئين في تطوير Android وهو مصمم للمساعدة في إنشاء الحد الأدنى المطلوب من بنية التطبيق.
لقد حدث أنني بدأت مؤخرًا برمجة لأجهزة Android - بعد شهر من عدم وجود مشروع في الشركة التي أعمل فيها ، تم تعييني لفريق تطوير الأجهزة المحمولة في مكتب أوروغواي لخدمات تاتا الاستشارية. عندما تحدثت مع فريق القيادة ، كان صوتي مكدسًا كان علي أن أتعرف عليه أولاً ، ثم أتقنه. من بين أشياء أخرى ، كان هناك إطار Dagger 2 لـ DI و MVP كنموذج معماري. وكوتلين. ولكن عنه مرة أخرى :)
لذلك ، بدأت في دراسة أساسيات Android SDK أولاً ، ثم المكدس المصاحب بأكمله. لم تكن هناك مشاكل مع SDK نفسها - فهناك أكثر من معلومات شاملة كافية على الشبكة ، بدءًا من الوثائق الرسمية وانتهاءً بالبرنامج التعليمي (ساعد مشروع startandroid بشكل خاص في هذا) ، ولكن كانت هناك بعض الصعوبات مع Dagger 2 و MVP فيما يتعلق بتطوير Android بسبب قصر بعض الشيء توثيق الأول ، وفي ذلك الوقت ، فهم غير كاف للثاني. والحقيقة هي أنه قبل تطوير الأجهزة المحمولة ، قمت بالخدمات المصغرة في جافا باستخدام Spring Boot / MVC وكان لدي فكرة جيدة بالفعل عن ماهية Dependency Injection وما هي MVC. علاوة على ذلك ، يشير اسم "Spring MVC" نفسه إلى أن هذا النمط مضمن في بنية المشروع وأن استخدامه واضح. من Dagger 2 كنت أتوقع نفس "السحر" كما هو الحال في Spring ونفس التوثيق والدروس التعليمية. وانقطع: P
ومع ذلك ، مع ما يكفي من المثابرة والمثابرة ، لا يوجد شيء مستحيل ، وكانت نتيجة البحث هي تنفيذ فكرتي القديمة ، والتي نشأت حتى في تلك الأيام التي لم أفكر فيها حتى في تطوير نظام Android. يمكنك تقييم الفكرة عن طريق تثبيت التطبيق من متجر Googleفي هذه المقالة ، أود تقديم ضغط جاف على نتائج عمليات البحث الخاصة بي - دليل خطوة بخطوة حول إنشاء الهيكل العظمي لتطبيق Android باستخدام MVP و Dagger 2. لذا ، فلنبدأ.
1.1 الملخصات
أولاً ، قم بإنشاء حزمة الملخصات في جذر المشروع ، فليكن com.caesar84mx.mymvcapp.abstracts. سنقوم بإنشاء واجهات 2 فيه: view.BaseView و presenter.BaseMvpPresenter. على النحو التالي:

هذه هي العناصر المعمارية الأساسية التي سيتم استخدامها لاحقًا في التطبيق. بعد ذلك ، افتح BaseView وقم بتعريف أساليب showView () getContext () فيه:
interface BaseView { fun showView(view: View, isShown: Boolean) { view.visibility = if (isShown) View.VISIBLE else View.GONE } fun getContext(): Context }
افتح الآن BaseMvpPresenter وقم بتحريره كما يلي:
interface BaseMvpPresenter<V: BaseView> { var isAttached: Boolean fun attach(view: V) fun detach() }
في حزمة العرض ، قم بإنشاء فئة BaseCompatActivity مجردة ، ورثتها من AppCompatActivity ، وتطبيق واجهة BaseView التي تم إنشاؤها حديثًا. داخل الفصل ، نعلن عن طريقة init abstract (saveInstanceState: Bundle؟) ونطبق طريقة getContext () من BaseView:
abstract class BaseCompatActivity: AppCompatActivity(), BaseView { override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { super.onCreate(savedInstanceState, persistentState) init(savedInstanceState) } protected abstract fun init(savedInstanceState: Bundle?) override fun getContext(): Context = this }
من هذه الفئة في المستقبل سوف نرث جميع الأنشطة.
الآن دعنا ننتقل إلى مقدم العرض - إنشاء فئة BasePresenter التي تنفذ واجهة BaseMvpPresenter وتنفيذ أساليب الواجهة على النحو التالي:
open class BasePresenter<V : BaseView> : BaseMvpPresenter<V> { protected var view: V? = null private set override var isAttached = view != null override fun attach(view: V) { this.view = view } override fun detach() { this.view = null } }
حسنًا ، لقد حددنا العناصر المعمارية الأساسية ، والآن دعنا ننتقل إلى المكونات التي سيتم بناء تطبيقنا منها.
1.2. مكونات
أولاً ، قم بإنشاء حزمة com.caesar84mx.mymvcapp.components ، وحزمة الشاشة الرئيسية ، والتي بدورها ، حزم واجهة المستخدم و backstage ، ونقل فئة الشاشة الرئيسية إلى حزمة واجهة المستخدم:

سنقوم الآن بإزالة تطبيق onCreate () من فئة MainScreen الذي تم إنشاؤه تلقائيًا عند إنشاء المشروع ، وكذلك الميراث من AppCompatActivity ورثه من BaseCompatActivity. الآن ننفذ طريقة init () المعلنة مسبقًا في الفئة الأساسية. جميع التعليمات البرمجية التي نضعها في طريقة onCreate () سابقًا ، نضعها (كما نذكر ، يتم استدعاء أسلوب init () في طريقة onCreate () للفئة الأساسية):
class MainScreen : BaseCompatActivity() { override fun init(savedInstanceState: Bundle?) { setContentView(R.layout.activity_main_screen) } }
رائع ، يتم إنشاء عنصر العرض لنمط MVP ، والآن دعنا نذهب إلى وراء الكواليس من المكون لدينا - حزمة وراء الكواليس. دعنا ننشئ واجهة MainScreenContract - العقد المزعوم الذي من خلاله سننفذ نمطنا. في هذه الواجهة ، قم بإنشاء واجهات فرعية 2 - مقدم العرض وعرض:
interface MainScreenContract { interface Presenter: BaseMvpPresenter<MainScreenContract.View> interface View: BaseView }
الآن ، دعنا ننتقل إلى مقدم العرض وإنشاء فئة MainScreenPresenter:
class MainScreenPresenter : BasePresenter<MainScreenContract.View>(), MainScreenContract.Presenter { }
الهيكل العظمي للتطبيق جاهز تقريبًا ، ولا تزال هناك بعض اللمسات. في فئة MainScreen ، أضف تطبيق واجهة MainScreenContract.View ، وقم بإنشاء وتهيئة متغير مقدم العرض: MainScreenPresenter ، وفي طريقة init () ، قم بإرفاق العرض إلى مقدم العرض كما يلي:
class MainScreen : BaseCompatActivity(), MainScreenContract.View { val presenter: MainScreenPresenter? = MainScreenPresenter() override fun init(savedInstanceState: Bundle?) { setContentView(R.layout.activity_main_screen) presenter?.attach(this) } }
وبالتالي ، أنشأنا مقدمًا وأضفنا إليه مثيلنا للعرض (يجب عدم الخلط بينه وبين android.view.View) ، والذي سيتم استخدامه في مقدم العرض لمعالجة العرض.
1.3. اختتام الجزء الاول
لذلك ، أنشأنا العناصر المجردة الأساسية لنمط MVP ، والتي ، مع ذلك ، لا يتم استخدامها بشكل مباشر ، على الجبهة ، ولكن من خلال ما يسمى. العقد - العنصر الأساسي لكل مكون من عناصر التطبيق ، والذي يجمع بين كل من إجراءات عنصر العرض وإجراءات عنصر مقدم العرض. العقد هو عنصر مرن إلى حد ما ، حيث يختلف تكوينه من مكون إلى مكون ، ويربط بشكل غير مزعج المكونات داخل بنية واحدة.
يجب أن نتذكر أنه وفقًا لمفهوم MVP ، يجب أن يكون عنصر العرض واضحًا قدر الإمكان ، حيث نقوم فقط بتنفيذ إجراءات أولية ، على سبيل المثال ، إظهار / إخفاء النص ، تغيير خلفية النص أو لونه ، إظهار / إخفاء رمز التنزيل ، إلخ. د. نحدد الطرق المقابلة لهذا العنصر في الواجهة الفرعية لعقد العرض. بينما نتعامل مع المنطق في مقدم - منطق الأعمال ، معالجة البيانات (CRUD) ، إطلاق مهام الخلفية ، إلخ. في ذلك ، نقرر متى تظهر عناصر معينة على الشاشة. يختلف هذا عن مفهوم MVC الذي تم تطبيقه في الربيع ، حيث يوجد بين منطق الأعمال وطريقة العرض وحدة تحكم غبية تتلقى طلبات من العرض وتدعو خدمة تُرجع البيانات أو تنفذ إجراءات أخرى محددة بواسطة منطق العمل. يتم تعريف الطرق المقابلة للمقدم في الواجهة الفرعية لعقد مقدم العرض.
عند تنفيذ مقدم العرض ، سيتم التعامل مع طريقة العرض من خلال متغير العرض من الطبقة الأساسية BasePresenter ، في حين يتم تنفيذ الأساليب المقابلة لطريقة العرض في فئة النشاط.
أنت تسأل ، أين يوجد Dagger 2 هنا ولماذا استسلم لنا ، هل سيقوم تطبيق DI في Android بسحب بومة على الكرة الأرضية؟ الجواب على السؤال الثاني هو لا ، لن. ولماذا ولماذا هو مطلوب - في
الجزء الثاني من مقالي ؛)