Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Android SDK
Code

جافا 8 لتطوير الروبوت: دفق API ومكتبات التاريخ الوقت &

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Java 8 for Android Development.
Java 8 for Android Development: Default and Static Methods

Arabic (العربية/عربي) translation by Aeni Amalia (you can also view the original English article)

في هذه السلسلة من ثلاثة أجزاء، ونحن لقد تم استكشاف كافة الميزات جافا 8 الرئيسية التي يمكنك البدء باستخدام في مشاريع الروبوت الخاص بك اليوم.

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

في هذا المنصب نهائياً، نحن ذاهبون إلى إلقاء نظرة على نوع الشروح وواجهات وظيفية وكيفية اتخاذ نهج أكثر وظيفية لمعالجة البيانات مع API جافا 8 لتيار جديد.

سأوضح لك أيضًا كيفية الوصول إلى بعض ميزات Java 8 الإضافية التي لا تدعمها حاليًا أنظمة Android الأساسية ، وذلك باستخدام مكتبات Joda-Time و ThreeTenABP.

نوع التعليقات التوضيحية

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

شروح ليست ميزة جديدة (في الواقع، أنها تعود إلى جافا 5.0)، ولكن في الإصدارات السابقة من جافا كان فقط يمكن تطبيق التعليقات التوضيحية على الإعلانات.

مع إصدار Java 8 ، يمكنك الآن استخدام التعليقات التوضيحية في أي مكان كنت تستخدم فيه نوعًا ما ، بما في ذلك أجهزة استقبال الأساليب ؛ تعبيرات إنشاء مثيل الفئة؛ تنفيذ واجهات ؛ الأدوية والمصفوفات مواصفات البنود والرميات وتنفيذها ؛ ونوع الصب.

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

توفر مكتبة دعم التعليقات التوضيحية في Android الوصول إلى بعض التعليقات التوضيحية الإضافية ، مثلNullable وNonNull والتعليقات التوضيحية للتحقق من صحة أنواع الموارد مثلDrawableRes وDimenRes وColorRes وStringRes. ومع ذلك ، قد ترغب أيضًا في استخدام أداة تحليل ثابتة لجهة خارجية ، مثل أداة Checker Framework ، التي تم تطويرها مع مواصفات JSR 308 (مواصفات التعليقات التوضيحية على أنواع جافا). يوفر هذا الإطار مجموعة خاصة به من التعليقات التوضيحية التي يمكن تطبيقها على الأنواع ، بالإضافة إلى عدد من "المدققين" (معالجات التعليق التوضيحي) التي تعلق بعملية التجميع وتجري "عمليات تدقيق" محددة لكل تعليق توضيحي يتضمنه في أداة Checker Framework.

منذ لا تؤثر على "نوع الشروح" العملية وقت التشغيل، يمكنك استخدام جافا 8 "نوع الشروح" في المشاريع الخاصة بك بينما تبقى معكوس متوافق مع الإصدارات القديمة من جافا.

دفق API

يوفر API تيار "أنابيب ومرشحات" نهج بديل، إلى مجموعات تجهيز.

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

API تيار يوفر لك طريقة لمعالجة البيانات أكثر كفاءة، بأداء شوط واحد على تلك البيانات — بغض النظر عن كمية البيانات التي كنت معالجة، أو إذا قمت بتنفيذ العديد من العمليات الحسابية.

في Java 8 ، تحتوي كل فئة تقوم بتنفيذ java.util.Collection على طريقة دفق تستطيع تحويل المثيلات الخاصة بها إلى كائنات Stream. على سبيل المثال ، إذا كان لديك صفيف:

ثم يمكن تحويله إلى تيار بما يلي:

تعالج Stream API البيانات عن طريق نقل قيم من مصدر ، من خلال سلسلة من الخطوات الحسابية ، المعروفة باسم خط أنابيب الدفق. يتكون خط أنابيب التدفق مما يلي:

  • مصدر، مثل وظيفة مجموعة أو صفيف أو مولد.
  • صفر أو أكثر عمليات "كسولة" متوسطة. لا تبدأ العمليات الوسيطة في معالجة العناصر حتى تستدعي عملية طرفية ، وهذا هو السبب في أنها تعتبر كسولة. على سبيل المثال ، استدعاء Stream.filter () على مصدر بيانات يقوم فقط بإعداد خط أنابيب الدفق؛ يحدث أي تصفية بالفعل حتى تقوم باستدعاء العملية الطرفية. هذا يجعل من الممكن سلسلة عمليات متعددة معا ، ومن ثم تنفيذ جميع هذه الحسابات في مسار واحد من البيانات. تنتج العمليات الوسيطة تيارًا جديدًا (على سبيل المثال ، ينتج الفلتر تيارًا يحتوي على العناصر التي تمت تصفيتها) دون تعديل مصدر البيانات ، بحيث يمكنك استخدام البيانات الأصلية في أي مكان آخر في مشروعك ، أو إنشاء تدفقات متعددة من المصدر نفسه.
  • عملية طرفية ، مثل Stream.forEach. عند استدعاء العملية الطرفية ، سيتم تشغيل كافة العمليات الوسيطة الخاصة بك وإنتاج دفق جديد. لا يستطيع الدفق تخزين العناصر ، لذلك بمجرد أن تستدعي تشغيلًا نهائيًا ، يتم اعتبار هذا البث "مستهلكًا" ولم يعد قابلاً للاستخدام. إذا كنت تريد إعادة زيارة عناصر مجموعة البث ، فحينئذٍ ستحتاج إلى إنشاء تدفق جديد من مصدر البيانات الأصلي.

إنشاء دفق

هناك طرق مختلفة للحصول على تيار من مصدر بيانات، بما في ذلك:

  • Stream.of() يخلق دفق من القيم الفردية:

  • IntStream.range() يخلق دفق من مجموعة من الأرقام:

  • Stream.iterate () إنشاء دفق بتطبيق عامل تشغيل بشكل متكرر على كل عنصر. على سبيل المثال ، نحن بصدد إنشاء تدفق حيث يزيد كل عنصر في القيمة بمقدار واحد:

تحويل تيار مع العمليات

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

خريطة

تأخذ عملية map () تعبير lambda كوسيطة فقط ، وتستخدم هذا التعبير لتحويل القيمة أو نوع كل عنصر في الدفق. على سبيل المثال ، يعطينا ما يلي دفقًا جديدًا ، حيث تم تحويل كل سلسلة إلى أحرف كبيرة:

الحد الأقصى

هذه العملية تضع حدا على حجم الدفق. على سبيل المثال، إذا أردت إنشاء دفق جديد يحتوي على قيمة خمسة كحد أقصى، ثم يمكنك أن استخدم ما يلي:

عامل التصفية

يتيح لك عامل التصفية (Predicate ) تحديد معايير التصفية باستخدام تعبير lambda. يجب أن يقوم تعبير lambda هذا بإرجاع قيمة منطقية تحدد ما إذا كان يجب تضمين كل عنصر في الدفق الناتج. على سبيل المثال ، إذا كان لديك مجموعة من السلاسل وأردت تصفية أي سلاسل تحتوي على أقل من ثلاثة أحرف ، فستستخدم ما يلي:

فرز

هذه العملية فرز عناصر تيار. على سبيل المثال، التالية إرجاع دفق أرقام مرتبة في ترتيب تصاعدي:

المعالجة المتوازية

يمكن تنفيذ جميع عمليات دفق في المسلسل أو بالتوازي، على الرغم من تيارات متتالية ما لم يتم تحديد خلاف ذلك صراحة. على سبيل المثال، التالية سيقوم بمعالجة كل عنصر واحداً تلو الآخر:

لتنفيذ تيار في وقت واحد ، تحتاج إلى وضع علامة على ذلك التدفق بشكل متوازٍ ، باستخدام الطريقة المتوازية ():

تحت غطاء محرك السيارة، استخدام تيارات موازية في "إطار" شوكة/الانضمام، حيث يساوي عدد مؤشرات الترابط المتوفرة دائماً عدد النوى المتوفرة في وحدة المعالجة المركزية.

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

عمليات محطة الشحن

تقوم بتجميع النتائج من دفق باستخدام عملية طرفية ، وهي دائمًا العنصر الأخير في سلسلة من طرق الدفق ، وتعيد دائمًا شيئًا آخر غير التدفق.

وهناك بضعة أنواع مختلفة من عمليات المحطة الطرفية التي تقوم بإرجاع أنواع مختلفة من البيانات، ولكن في هذا القسم سنقوم بإلقاء نظرة على اثنين من عمليات المحطة الطرفية الأكثر استخداماً.

جمع

تجمع عملية التجميع جميع العناصر التي تمت معالجتها في حاوية ، مثل قائمة أو مجموعة. توفر Java 8 فئة أدوات المساعدة الخاصة بـ Collectors ، لذا لا داعي للقلق بشأن تنفيذ واجهة Collectors ، بالإضافة إلى المصانع الخاصة بالكثير من المجمعات الشائعة ، بما في ذلك toList () و toSet () و toCollection ().

ستنتج التعليمة البرمجية التالية قائمة تحتوي على أشكال حمراء فقط:

بدلاً من ذلك ، يمكنك جمع هذه العناصر التي تمت تصفيتها في مجموعة:

forEach

تؤدي عملية forEach () بعض الإجراءات على كل عنصر من عناصر مجموعة البث ، مما يجعلها مكافئة لواجهة برمجة تطبيقات Stream API لكل عبارة.

إذا كان لديك قائمة عناصر ، فيمكنك استخدام forEach لطباعة كافة العناصر المضمنة في هذه القائمة:

في المثال أعلاه نحن نستخدم تعبير لامدا، ولذلك فمن الممكن القيام بنفس العمل في تعليمات برمجية أقل، باستخدام مرجع أسلوب:

واجهات وظيفية

واجهة وظيفية هي واجهة التي تحتوي على أسلوب تجريدي واحد بالضبط، المعروفة بطريقة وظيفية.

إن مفهوم الواجهات ذات الأسلوب الواحد ليس جديدًا ، حيث يُعد كل من Runnable و Comparator و Callable و OnClickListener أمثلة على هذا النوع من الواجهة ، على الرغم من أنها كانت تُعرف في الإصدارات السابقة من Java باسم واجهات الأسلوب Abstract المفرد (واجهات SAM).

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

قبل Java 8 ، تقوم عادة بإنشاء واجهة وظيفية باستخدام تطبيق فئة مجهول كبير. على سبيل المثال ، هنا نقوم بإنشاء مثيل من Runnable باستخدام فصل مجهول:

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

تقدم Java 8 أيضًا تعليقًا توضيحيًاFunctionalInterface يتيح لك تمييز واجهة كواجهة وظيفية:

لضمان التوافق مع الإصدارات السابقة من Java ، يكون التعليق التوضيحيFunctionalInterface اختياريًا ؛ ومع ذلك ، يوصى بالمساعدة في ضمان تنفيذ واجهات التعامل الوظيفية بشكل صحيح.

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

وإذا حاولت ترجمة واجهةFunctionInterface تحتوي على صفر طريقة ، فحينئذٍ ستواجه خطأ "لا يوجد هدف محدد".

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

كما أضاف Java 8 حزمة java.util.function تحتوي على الكثير من الواجهات الوظيفية. من المفيد قضاء بعض الوقت في التعرف على كل هذه الواجهات الوظيفية الجديدة ، حتى تعرف بالضبط ما هو متاح من العلبة.

جسر-310: جديدة التاريخ والوقت API جافا

لم يكن العمل مع التاريخ والوقت في Java أبداً بشكل مباشر ، مع وجود العديد من واجهات برمجة التطبيقات التي تحذف وظائف هامة ، مثل معلومات المنطقة الزمنية.

قدمت Java 8 واجهة برمجة تطبيقات جديدة للتاريخ والوقت (JSR-310) تهدف إلى حل هذه المشكلات ، ولكن للأسف في وقت كتابة هذا التطبيق ، لا يتم دعم واجهة برمجة التطبيقات هذه على نظام Android الأساسي. ومع ذلك ، يمكنك استخدام بعض ميزات التاريخ والوقت الجديدة في مشروعات Android اليوم ، باستخدام مكتبة جهة خارجية.

في هذا القسم الأخير، أنا ذاهب لتظهر لك كيفية إعداد واستخدام اثنين شعبية طرف ثالث المكتبات التي تجعل من الممكن استخدام جافا 8 في تاريخ ووقت API على الروبوت.

Backport ثريتين الروبوت

ThreeTen Android Backport (يُعرف أيضًا باسم ThreeTenABP) هو عبارة عن تكيُّف مع مشروع ThreeTen backport الشهير ، والذي يوفر تطبيقًا لـ JSR-310 لـ Java 6.0 و Java 7.0. تم تصميم ThreeTenABP لتوفير الوصول إلى جميع فصول API لوقت وتاريخ (وإن كان مع اسم حزمة مختلفة) دون إضافة عدد كبير من الطرق لمشاريع Android الخاصة بك.

لبدء استخدام هذه المكتبة ، افتح ملف build.gradle على مستوى الوحدة النمطية وأضف ThreeTenABP كاعتمادية للمشروع:

ثم تحتاج إلى إضافة عبارة الاستيراد ثريتينابب:

وتهيئة معلومات المنطقة الزمنية في أسلوب Application.onCreate () الخاص بك:

ثريتينابب يحتوي على فئتين التي تعرض "نوعين" من معلومات التاريخ والوقت:

  • لوكالداتيتيمي، الذي يقوم بتخزين وقت وتاريخ بشكل عام 2017-10-16T13:17:57.138
  • ZonedDateTime ، وهي منطقة زمنية على دراية وتقوم بتخزين معلومات التاريخ والوقت بالتنسيق التالي: 2011-12-03T10: 15: 30 + 01: 00 [أوروبا / باريس]

لإعطائك فكرة عن كيفية استخدامك لهذه المكتبة لاسترداد معلومات التاريخ والوقت ، فلنستخدم فئة LocalDateTime لعرض التاريخ والوقت الحاليين:

Display the date and time using the ThreeTen Android Backport library

هذه ليست الطريقة الأكثر سهولة في عرض التاريخ والوقت! لتحليل هذه البيانات الأولية إلى شيء أكثر قابلية للقراءة ، يمكنك استخدام فئة DateTimeFormatter وتعيينها إلى إحدى القيم التالية:

  • BASIC_ISO_DATE. تنسيقات التاريخ كعام 2017-1016 + 01.00
  • ISO_LOCAL_DATE. تنسيقات التاريخ كعام 2017-10-16
  • ISO_LOCAL_TIME. تنسيقات الوقت ك 14:58:43.242
  • ISO_LOCAL_DATE_TIME. تنسيقات التاريخ والوقت كعام 2017-10-16T14:58:09.616
  • ISO_OFFSET_DATE. تنسيقات التاريخ كعام 2017-10-16 + 01.00
  • ISO_OFFSET_TIME. تنسيقات الوقت ك 14:58:56.218 + 01:00
  • ISO_OFFSET_DATE_TIME. تنسيقات التاريخ والوقت كعام 2017-10-16T14:5836.758 + 01:00
  • ISO_ZONED_DATE_TIME. تنسيقات التاريخ والوقت ك 2017-10-16T14:58:51.324+01:00(Europe/London)
  • ISO_INSTANT. تنسيقات التاريخ والوقت كعام 2017-10-16T13:52:45.246Z
  • ISO_DATE. تنسيقات التاريخ كعام 2017-10-16 + 01:00
  • ISO_TIME. تنسيقات الوقت ك 14:58:40.945 + 01:00
  • ISO_DATE_TIME. تنسيقات التاريخ والوقت ك 2017-10-16T14:55:32.263+01:00(Europe/London)
  • ISO_ORDINAL_DATE. تنسيقات التاريخ كعام 2017-289 + 01:00
  • ISO_WEEK_DATE. لتنسيق التاريخ كـ 2017-W42-1 + 01: 00
  • RFC_1123_DATE_TIME. لتنسيق التاريخ والوقت كـ Mon، 16 OCT 2017 14: 58: 43 + 01: 00

هنا ، نعمل على تحديث تطبيقنا لعرض التاريخ والوقت مع تنسيق التاريخ DateTimeFormatter.ISO_DATE:

لعرض هذه المعلومات بتنسيق مختلف ، ما عليك سوى استبدال DateTimeFormatter.ISO_DATE بقيمة أخرى. فمثلا:

Joda-الوقت

قبل Java 8 ، اعتبرت مكتبة Joda-Time مكتبة قياسية للتعامل مع التاريخ والوقت في Java ، إلى النقطة التي تستقطب فيها واجهة برمجة تطبيقات التاريخ والوقت الجديدة لـ Java 8 "بشكل كبير على الخبرة المكتسبة من مشروع Joda-Time".

على الرغم من أن موقع ويب Joda-Time يوصي بأن يقوم المستخدمون بالترحيل إلى Java 8 Date and Time بأسرع وقت ممكن ، نظرًا لأن Android لا يدعم حاليًا واجهة برمجة التطبيقات هذه ، فإن Joda-Time لا يزال خيارًا صالحًا لتطوير Android. ومع ذلك ، لاحظ أن Joda-Time تحتوي على واجهة برمجة تطبيقات كبيرة وتحمّل معلومات المنطقة الزمنية باستخدام مورد JAR ، ويمكن أن يؤثر كلاهما على أداء تطبيقك.

لبدء العمل مع مكتبة Joda-Time ، افتح ملف build.gradle على مستوى الوحدة النمطية وأضف ما يلي:

وقد مكتبة وقت Joda ستة تاريخ الرئيسية وفئات وقت:

  • التراسل الفوري: يمثل نقطة في الخط الزمني؛ على سبيل المثال، يمكنك الحصول على التاريخ الحالي والوقت عن طريق استدعاء Instant.now().
  • التاريخ والوقت: استبدال الأغراض عامة لفئة التقويم لجدك.
  • لوكالداتي: تاريخ دون وقت، أو أي إشارة إلى منطقة زمنية.
  • LocalTime: وقت دون تاريخ أو أية إشارة إلى منطقة زمنية، على سبيل المثال 14:00.
  • لوكالداتيتيمي: وقت وتاريخ المحلية، ما زالت دون أية معلومات المنطقة الزمنية.
  • زونيداتيتيمي: تاريخ ووقت مع منطقة الزمنية.

دعنا نلقي نظرة على كيفية طباعة التاريخ والوقت باستخدام Joda-Time. في المثال التالي ، أعيد استخدام الرمز من مثال ThreeTenABP ، لذلك لجعل الأشياء أكثر تشويقًا ، فأنا أستخدم أيضًا مع المنطقة لتحويل التاريخ والوقت إلى قيمة ZonedDateTime.

Display the date and time using the Joda-Time library

ستجد قائمة كاملة للمناطق الزمنية المعتمدة في وقت Joda مستندات رسمية.

الاستنتاج

في هذه المشاركة ، نظرنا في كيفية إنشاء شفرة أكثر قوة باستخدام التعليقات التوضيحية من النوع ، واستكشفنا منهج "الأنابيب والتصفية" لمعالجة البيانات باستخدام واجهة برمجة تطبيقات Stream الجديدة في جافا 8.

كما نظرنا في كيف تطورت واجهات في جافا 8 وكيفية استخدامها في تركيبة مع ميزات أخرى نحن لقد تم استكشاف طوال هذه السلسلة، بما في ذلك تعبيرات لامدا وأساليب الواجهة ثابتة.

لإنهاء الأمور، أنا أظهر لك كيفية الوصول إلى بعض الميزات الإضافية جافا 8 الروبوت حاليا يعتمد بشكل افتراضي، استخدام المشاريع Joda-الوقت وثريتينابب.

يمكنك معرفة المزيد حول إصدار Java 8 في موقع Oracle.

وفي حين كنت هنا، تحقق بعض الوظائف الأخرى لدينا حول جافا 8 وتطوير الروبوت!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.