مقدمة
Kotlin Coroutines هي واجهة برمجة تطبيقات جديدة غير متزامنة أطلقتها Kotlin. ليس أفضل حل لجميع المشكلات ، ولكن نأمل في كثير من الحالات أن يجعل الأمور أسهل قليلاً. هنا سأعرض ببساطة خطة الاستخدام المحددة لهذه المكتبة في Android. لن أقول الكثير أدناه ، دعنا نلقي نظرة على المقدمة التفصيلية معًا.
تقديم coroutines
// أضف الكود التالي في عقدة Android في ملف build.gradle للتطبيق kotlin {التجريبي {coroutines 'enable'}}}} // أضف الخطين التاليين إلى تطبيق التبعية "org.jetbrains.kotlinx: kotlinx-coroutines-core: 0.20" org.jetbrains.kotlinx: kotlinx: 0.20.مثال أول كوروتين
عادةً ما نقوم بتحميل صورة في ImageView ، ومهمة التحميل غير المتزامنة هي كما يلي:
funbitmapfrommediastore (ImageId: int ، imagesbaseuri: uri): bitmap {val uri = uri.withappendedpath (picturebaseuri ، imageid.toString ())يجب تنفيذ هذه الطريقة في مؤشر ترابط الخلفية لأنها تنتمي إلى عملية IO ، مما يعني أن لدينا العديد من الحلول لبدء مهمة الخلفية ، وبمجرد إرجاع الطريقة إلى صورة نقطية ، نحتاج إلى عرضه في ImageView على الفور.
ImageView.setImageBitMap (صورة نقطية)
يجب تنفيذ خط الرمز هذا في الخيط الرئيسي ، وإلا فإنه سيتعطل.
إذا تمت كتابة الأسطر الثلاثة المذكورة أعلاه من الكود معًا ، فسيتم تعليق البرنامج أو تعطله ، وهو ما يعتمد على اختيار معقول للمواضيع. بعد ذلك ، دعونا نلقي نظرة على كيفية حل Coroutines باستخدام Kotlin هذه المشكلة:
Val Job = Launch (background) {val uri = uri.withappendedPath (imagesbaseuri ، imageid.toString ()) val bitmap = mediaStore.images.media.getBitMap (contentResolver ، launch (ui) {imageview.setimagebitmap (bibmap)}}}}}}}}}}}}}}}}}}}}}الشيء الأكثر أهمية هنا هو Launch () والمعلمات الخلفية وواجهة المستخدم. إطلاق () يعني إنشاء وبدء coroutine. يتم استخدام معلمة الخلفية coroutinecontext لضمان التنفيذ في مؤشر ترابط الخلفية ، وذلك لضمان عدم تعليق التطبيق أو تعطله. يمكنك إعلان coroutinecontext كما هو موضح أدناه.
خلفية Val الداخلية = NewfixedThreadPoolContext (2 ، "BG")
هذا يخلق سياقًا جديدًا ويستخدم خيطين عاديين عند تنفيذ مهامه.
بعد ذلك ، الإطلاق (UI) ، الذي سيؤدي إلى توجيه coroutine آخر ، والذي سيتم تنفيذه على Android
الموضوع الرئيسي.
قابل للإلغاء
التحدي التالي هو التعامل مع الأشياء المتعلقة بدورة إعلان النشاط. عند تحميل مهمة وترك النشاط قبل الانتهاء من التنفيذ ، سيؤدي ذلك إلى تعطل عند استدعاء imageView.setImageBitmap(bitmap) ، لذلك نحتاج إلى إلغاء المهمة قبل مغادرة النشاط. هنا نستخدم قيمة الإرجاع لطريقة الإطلاق (). عندما يستدعي النشاط طريقة ONSTOP ، نحتاج إلى استخدام المهمة لإلغاء المهمة.
Job.cancel ()
إنه مثل استدعاء Dispose عند استخدام وظيفة Rxjava واتصال Conclude عند استخدام Asynctask.
دورة الحياة
توفر مكونات الهندسة المعمارية Android مطوري Android مع العديد من المكتبات القوية ، إحداها هي واجهة برمجة تطبيقات دورة الحياة. يوفر لنا طريقة سهلة للاستماع إلى دورة حياة الأنشطة والشظايا في الوقت الفعلي. دعنا نحدد الكود لاستخدامه مع coroutines.
class coroutinelifecyclelistener (val مؤلف: مؤجل <*>): LifecyCleObserver {onlifecyclevent (lifecycle.event.on_destroy) متعة cancelCoroutine () {if (! deferred.iscancelled)نقوم بإنشاء وظيفة تمديد دورة الحياة:
متعة <T> lifecleCleOwner.Load (loader: () -> t): مؤلف <T> {val eDefred = async (context = background ، start = coroutinestart.lazy) {loader () هناك الكثير من الأشياء الجديدة في هذه الطريقة ، وسأشرحها واحدًا تلو الآخر:
الآن يمكننا استدعاء load() في نشاط أو جزء والوصول إلى أعضاء دورة الحياة من هذه الوظيفة وإضافة coroutinelifecyclelistener كمراقب.
تتطلب طريقة التحميل محملًا كمعلمة ، وإرجاع نوع عام T. في طريقة التحميل ، نسمي وظيفة Coroutine Creator Async () أخرى ، والتي ستستخدم سياق Coroutine الخلفية لتنفيذ المهام في مؤشر ترابط الخلفية. لاحظ أن هذه الطريقة لها معلمة أخرى start = coroutinestart.lazy ، مما يعني أنه لن يتم تنفيذ coroutine على الفور ، حتى يتم استدعاؤه.
ستعيد Coroutine بعد ذلك كائنًا Defered<T> إلى المتصل ، وهو مشابه لوظيفتنا السابقة ، ولكنه يمكن أن يحمل أيضًا قيمة تأخير ، مثل JavaScript Promise أو Future <T> في واجهة برمجة تطبيقات Java العادية ، وحتى أفضل ، لها طريقة انتظار.
بعد ذلك ، نحدد وظيفة تمديد أخرى then() ، هذه المرة نحددها فوق Deferen<T> ، وهو النوع الذي يتم إرجاعه بواسطة طريقة التحميل لدينا أعلاه. كما أنه يأخذ lambda كمعلمة ، المسماة Block ، والتي تأخذ كائن واحد من النوع T كمعلمة له.
infix fun <t> مؤلف <T> .Then (block: (t) -> الوحدة): Job {return launch (context = ui) {block ([email protected] ())}} ستقوم هذه الوظيفة بإنشاء coroutine آخر باستخدام وظيفة launch() ، والتي سيتم تشغيلها على الخيط الرئيسي هذه المرة. يأخذ Lambda (المسمى Block) الذي تم تمريره إلى هذا Coroutine قيمة الكائن المؤجل المكتمل كمعلمة له. ندعو await() لتعليق تنفيذ هذا coroutine حتى يعيد الكائن المؤجل قيمة.
هنا حيث يصبح كوروتين مثيرًا للإعجاب. تتم الدعوة إلى await() على الموضوع الرئيسي ، ولكن لا تمنع المزيد من تنفيذ هذا الموضوع. سوف يتوقف ببساطة عن تنفيذ الوظيفة حتى يصبح جاهزًا ، عندما يستأنف ويمرر القيمة المتأخرة إلى Lambda. عندما يتم تعليق Coroutine ، يمكن للخيط الرئيسي أن يستمر في أداء أشياء أخرى. وظيفة الانتظار هي مفهوم أساسي في Coroutine ، ما يخلق كل شيء سحري للغاية.
سيقوم مراقب دورة الحياة المضافة في وظيفة load() بإلغاء أول coroutine بعد استدعاء onDestroy() على نشاطنا. سيؤدي ذلك أيضًا إلى إلغاء Coroutine الثاني ، ومنع block() .
Kotlin Coroutine DSL
الآن بعد أن أصبح لدينا وظيفتان تمديد وفئة تتعامل مع إلغاء Coroutine ، دعونا نرى كيفية استخدامه:
load {loadbitmapfrommediastore (ImageId ، imagesbaseuri)} ثم {imageView.setImageBitMap (it)} في الكود أعلاه ، نقوم بتمرير طريقة lambda إلى وظيفة التحميل ، والتي تستدعي طريقة LoadBitMapfRommediastore ، والتي يجب تنفيذها على مؤشر ترابط الخلفية حتى تُرجع الطريقة صورة نقطية ، ويتم Deferred<Bitmap> .
كدالة تمديد ، تستخدم طريقة then() إعلان Infix. على الرغم من إرجاع طريقة التحميل Deferred<Bitmap> ، إلا أنه سيتم تمريرها إلى الطريقة التي آنذاك قيمة إرجاع صورة نقطية ، حتى نتمكن من الاتصال مباشرة بـ imageView.setImageBitmap(it) في الطريقة ثم.
يمكن استخدام الرمز أعلاه لأي مكالمات غير متزامنة تحتاج إلى حدوثها في مؤشر ترابط الخلفية ، وحيث يجب إرجاع قيمة الإرجاع إلى الخيط الرئيسي ، كما هو الحال في المثال أعلاه. لا يجري مكالمات متعددة كما يفعل Rxjava ، ولكن من الأسهل القراءة وقد تغطي الكثير من الحالات الأكثر شيوعًا. الآن يمكنك أن تفعل شيئًا كهذا بأمان دون القلق بشأن التسبب في تسرب السياق أو معالجة الخيوط في كل مكالمة ؛
load {restapi.fetchdata (query)} ثم {adapter.display (it)}ثم () و Load () أساليب هي مجرد غيض من الجبل الجليدي لهذه المكتبة الجديدة ، لكنني آمل أن يظهر شيء مشابه في مكتبات Android المستندة إلى Kotlin بمجرد وصول إصدار Coroutine إلى إصدار مستقر. قبل ذلك ، يمكنك استخدام أو تعديل الرمز أعلاه ، أو تحقق من Anko Coroutines. كما أصدرت نسخة أكثر اكتمالا على جيثب. (https://github.com/erikhellman/kotlinasyncwithcoroutines (التنزيل المحلي)).
لخص
ما سبق هو المحتوى الكامل لهذه المقالة. آمل أن يكون لمحتوى هذه المقالة قيمة مرجعية معينة لدراسة أو عمل الجميع. إذا كان لديك أي أسئلة ، فيمكنك ترك رسالة للتواصل. شكرا لك على دعمك إلى wulin.com.