التنقل داخل تطبيق Android

مقدمة


مع تطوير Android ، نستخدم الحلول المعمارية المختلفة (الأنماط). على سبيل المثال ، Mvp ، Mvvm ، Mvi ، إلخ ... يحل كل من هذه الأنماط العديد من المشكلات المهمة ، ولأنها ليست مثالية ، فإنها تترك لنا بعض المشكلات التي لم يتم حلها. على سبيل المثال ، تتضمن هذه المهام التنقل داخل التطبيق (التوجيه) ، ونقل المعلومات من شاشة إلى أخرى (تحدث الشاشة ، أقصد النشاط ، أو التجزئة ، أو العرض) ، وحفظ حالة التطبيق عند تغيير التكوين (تغيير التكوين).


في شركتنا ، واجهنا هذه المشكلات أيضًا ، تم حل بعضها بطريقة سهلة ، لكن أولها لم يجد حلاً محددًا ، بعد تجربة طرق مختلفة لحلها ، كتبنا مكتبة Flowzard الخاصة بنا .


التحدي


في شركتنا ، نستخدم بنية Mvp . لتحقيق أقصى قدر من المرونة عند عرض البيانات وتغييرها ونقلها بين الشاشات ، نحاول اتباع المبدأ المسمى مبدأ المسؤولية الفردية . ينص المبدأ على أن كل وحدة يجب أن تحل مشكلة محددة. في حالتنا ، يجب عزل الشاشة عن المهمة العالمية ويجب أن تحل مهمتها المحددة المتمثلة في إظهار / تلقي المعلومات. يجب أن لا يعرف عن الشاشات الأخرى على الإطلاق. حتى نتمكن من تحقيق أقصى قدر من المرونة. فيما يلي مثال على إعداد واستخدام المكتبة.


Flowzard


خلق التدفق


class MainFlow(flowManager: FlowManager) : Flow(flowManager) { //      flow override fun onCreate(savedInstance: DataBunch?, data: DataBunch?) { super.onCreate(savedInstance, data) } } 

إنشاء تدفق الملاح


يؤدي المستكشفون وظيفتين: إنشاء حاويات التدفق (نشاط ، تجزئة ، عرض) للتحولات بين التدفق وشاشات للتحولات داخل التدفق.


 class DefaultFlowNavigator(activity: AppCompatActivity) : SimpleFlowNavigator(activity){ //    flow  Activity override fun getActivityIntent(id: String, data: Any?): Intent { return when (id) { Flows.SIGN_UP -> Intent(activity, SignupActivity::class.java) else -> throw RuntimeException("Cannot find activity for id=$id") } } } 

انجذاب إلى النشاط


لربط النشاط بـ Flow ، نرث FlowActivity ونوفر Navigator ، في حالتنا DefaultFlowNavigator.


 class MainActivity : FlowActivity() { override val navigator: Navigator get() = DefaultFlowNavigator(this) } 

إنشاء FlowManager


 class DefaultFlowManager : FlowManager() { //    (main) flow override fun createMainFlow(): Flow { return MainFlow(this) } //    flow override fun createFlow(id: String): Flow { return when (id) { Flows.SIGN_UP -> SignupFlow(this) else -> throw RuntimeException("Cannot find flow for id=$id") } } } //   FlowManager  Application class App : Application(), FlowManagerProvider { private val flowManager = DefaultFlowManager() override fun getProvideManager(): FlowManager { return flowManager } } 

المراسلة بين التدفق والشاشة


عند النقر فوق زر تسجيل الدخول ، يرسل النشاط رسالة إلى التدفق الرئيسي. ينشئ التدفق تدفق SIGN_UP وينتظر استجابة منه. في حالة نجاح تسجيل الدخول ، يرسل تدفق SIGN_UP النتيجة إلى التدفق الرئيسي و onFlowResult: يسمى MainFlow بالرمز وكائن النتيجة. يتحقق التدفق الرئيسي من صحة النتيجة ، ثم يرسل رسالة مرة أخرى إلى التنشيط الذي قام المستخدم بتسجيل الدخول بنجاح.


 class MainFlow(flowManager: FlowManager) : Flow(flowManager) { companion object { const val LOGIN_REQUEST_CODE = 1 } //     override fun onMessage(code: String, message: Any) { super.onMessage(code, message) if (code == "main" && message == "login") { newFlow(Flows.SIGN_UP, LOGIN_REQUEST_CODE) } } //       flow override fun onFlowResult(requestCode: Int, result: Result) { super.onFlowResult(requestCode, result) if (requestCode == LOGIN_REQUEST_CODE && result is Result.SUCCESS) { sendMessageFromFlow("main", true) } } } class MainActivity : FlowActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) loginButton.setOnClickListener { //   “login”   “main” flow.sendMessage("main", "login") } //     “main” setMessageListener("main") { if (it is Boolean && it) { statusTextView.text = "Logined" } } } } 

حفظ الحالة عند تغيير التكوين أو عندما تتوقف العملية عن نظام التشغيل


نظرًا لأن Android يحفظ مجموعات النشاط و Fragment ، فإن التدفقات التي تم إنشاؤها باستخدام هذه الحاويات ستوفر حالتها وتستعيدها. باستخدام حاوية "العرض" ، ستحتاج إلى كتابة FlowManager المخصص لأن المكتبة لا يوجد بها مثل هذا المدير بعد. في التحديث القادم ، ستكون هناك ميزة لحفظ البيانات الوسيطة من التدفق.


بما أنني لم أرغب في الحصول على الكثير من التعليمات البرمجية في المقالة ، فسأقتصر على هذا المثال. هنا رابط إلى مستودع الدراسة التفصيلية للمكتبة.

Source: https://habr.com/ru/post/ar435248/


All Articles