يتوافق مسار عرض الرسومات الثنائية الأبعاد في Android مع ميزة تسريع الأجهزة، ما يعني أنّ جميع عمليات الرسم التي يتم تنفيذها على لوحة الرسم تستخدم وحدة معالجة الرسومات. وبسبب زيادة الموارد المطلوبة لتفعيل ميزة "تسريع الأجهزة"، سيستهلك تطبيقك المزيد من ذاكرة الوصول العشوائي (RAM).
تكون ميزة "تسريع الأجهزة" مفعَّلة تلقائيًا. إذا كان تطبيقك يستخدم عناصر قابلة للإنشاء عادية فقط، لن يؤدي تفعيل هذا الخيار على مستوى العالم إلى حدوث أي تأثيرات سلبية في الرسم. ومع ذلك، بما أنّ ميزة "تسريع الأجهزة" لا تتوافق مع جميع عمليات الرسم الثنائي الأبعاد، قد يؤثّر تفعيلها في بعض طلبات الرسم المخصّص. تظهر المشاكل عادةً على شكل عناصر غير مرئية أو استثناءات أو وحدات بكسل معروضة بشكل خاطئ. ولحلّ هذه المشكلة، يتيح لك نظام التشغيل Android إمكانية تفعيل ميزة تسريع الأجهزة أو إيقافها على مستويات متعددة. اطّلِع على التحكّم في تسريع الأجهزة.
إذا كان تطبيقك ينفّذ عمليات رسم مخصّصة، اختبِر تطبيقك على أجهزة فعلية مع تفعيل ميزة تسريع الأجهزة للعثور على أي مشاكل. يوضّح قسم إتاحة عمليات الرسم المشاكل المعروفة المتعلقة بتسريع الأجهزة وكيفية حلّها.
يمكنك أيضًا الاطّلاع على OpenGL مع واجهات برمجة التطبيقات لإطار العمل.
التحكّم في ميزة "تسريع الأجهزة"
يمكنك التحكّم في تسريع الأجهزة على المستويات التالية:
- التطبيق
- النشاط
- نافذة
- قابلة للتركيب
مستوى التطبيق
في ملف بيان Android، أضِف السمة التالية إلى العلامة <application> لتفعيل تسريع الأجهزة للتطبيق بأكمله:
<application android:hardwareAccelerated="true" ...>
مستوى النشاط
إذا كان تطبيقك لا يعمل بشكل صحيح عند تفعيل ميزة "تسريع الأجهزة" على مستوى العالم، يمكنك التحكّم فيها للأنشطة الفردية أيضًا. لتفعيل ميزة تسريع الأجهزة أو إيقافها على مستوى النشاط، يمكنك استخدام السمة android:hardwareAccelerated للعنصر <activity>. يُفعّل المثال التالي تسريع الأجهزة للتطبيق بأكمله، ولكنّه يوقفه لأحد الأنشطة:
<application android:hardwareAccelerated="true">
<activity ... />
<activity android:hardwareAccelerated="false" />
</application>
مستوى النافذة
إذا كنت بحاجة إلى تحكّم أكثر دقة، يمكنك تفعيل تسريع الأجهزة لنافذة معيّنة باستخدام الرمز التالي:
window.setFlags(
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
)
المستوى القابل للإنشاء
في Compose، لا يتوفّر مفتاح تبديل لكل عنصر قابل للإنشاء لإيقاف ميزة "تسريع الأجهزة".
لعرض دالة مركّبة في طبقتها الخاصة، استخدِم Modifier.graphicsLayer. يتيح ذلك تغيير خصائص التحويل (مثل alpha وscaleX وscaleY وtranslationX وtranslationY وrotationX وrotationY وrotationZ وtransformOrigin) بدون إعادة تشغيل رمز الرسم للعنصر القابل للإنشاء. للحصول على أفضل أداء، استخدِم دائمًا صيغة lambda للمعدِّل لضبط هذه الخصائص.
لفرض استخدام مخزن مؤقت خارج الشاشة بشكل صريح لإجراء عمليات رسم متقدمة، مثل المزج المخصّص داخل الطبقة، استخدِم CompositingStrategy.Offscreen.
لمزيد من المعلومات، يُرجى الاطّلاع على معدِّلات الرسومات.
إذا كان لديك عملية رسم مخصّصة تتطلّب عرضًا برمجيًا، يمكنك استضافة عرض قديم باستخدام AndroidView واستدعاء setLayerType(View.LAYER_TYPE_SOFTWARE, null) على هذا العرض.
إتاحة عمليات الرسم
عندما يتم تسريع الأجهزة، يتيح مسار عرض الرسومات ثنائية الأبعاد عمليات الرسم Canvas الأكثر استخدامًا، بالإضافة إلى العديد من العمليات الأقل استخدامًا. تتوفّر جميع عمليات الرسم المستخدَمة لعرض التطبيقات التي تأتي مع Android، والعناصر القابلة للإنشاء العادية، والتأثيرات المرئية المتقدّمة الشائعة، مثل الانعكاسات والمواد المنسَّقة.
يوضّح الجدول التالي مستوى التوافق مع العمليات المختلفة على مستوى إصدارات واجهة برمجة التطبيقات:
| أول مستوى لواجهة برمجة التطبيقات متوافق | ||||
| Canvas | ||||
| drawBitmapMesh() (مصفوفة الألوان) | 18 | |||
| drawPicture() | 23 | |||
| drawPosText() | 16 | |||
| drawTextOnPath() | 16 | |||
| drawVertices() | 29 | |||
| setDrawFilter() | 16 | |||
| clipPath() | 18 | |||
| clipRegion() | 18 | |||
| clipRect(Region.Op.XOR) | 18 | |||
| clipRect(Region.Op.Difference) | 18 | |||
| clipRect(Region.Op.ReverseDifference) | 18 | |||
| clipRect() مع التدوير/المنظور | 18 | |||
| طلاء | ||||
| setAntiAlias() (للنص) | 18 | |||
| setAntiAlias() (للخطوط) | 16 | |||
| setFilterBitmap() | 17 | |||
| setLinearText() | ✗ | |||
| setMaskFilter() | ✗ | |||
| setPathEffect() (للخطوط) | 28 | |||
| setShadowLayer() (باستثناء النص) | 28 | |||
| setStrokeCap() (للخطوط) | 18 | |||
| setStrokeCap() (للنقاط) | 19 | |||
| setSubpixelText() | 28 | |||
| Xfermode | ||||
| PorterDuff.Mode.DARKEN (إطار التخزين المؤقت) | 28 | |||
| PorterDuff.Mode.LIGHTEN (إطار التخزين المؤقت) | 28 | |||
| PorterDuff.Mode.OVERLAY (إطار المخزن المؤقت) | 28 | |||
| Shader | ||||
| ComposeShader داخل ComposeShader | 28 | |||
| تظليلات من النوع نفسه داخل ComposeShader | 28 | |||
| المصفوفة المحلية في ComposeShader | 18 | |||
تحجيم لوحة العرض
تم إنشاء مسار عرض ثنائي الأبعاد مسرّع للأجهزة أولاً لتوفير إمكانية الرسم بدون تغيير الحجم، مع العلم أنّ بعض عمليات الرسم تؤدي إلى انخفاض كبير في الجودة عند استخدام قيم أعلى لتغيير الحجم. يتم تنفيذ هذه العمليات كصور يتم رسمها بمقياس 1.0، ويتم تحويلها بواسطة وحدة معالجة الرسومات. بدءًا من المستوى 28 لواجهة برمجة التطبيقات، يمكن تغيير حجم جميع عمليات الرسم بدون أي مشاكل.
يوضِّح الجدول التالي الحالات التي تم فيها تغيير التنفيذ للتعامل بشكل صحيح مع المقاييس الكبيرة:
| عملية الرسم التي سيتم تغيير حجمها | أول مستوى لواجهة برمجة التطبيقات متوافق |
| drawText() | 18 |
| drawPosText() | 28 |
| drawTextOnPath() | 28 |
| الأشكال البسيطة | 17 |
| الأشكال المعقّدة | 28 |
| drawPath() | 28 |
| طبقة الظل | 28 |
إذا لم يتم تسريع عملية رسم تعتمد عليها باستخدام الأجهزة، عليك عرض الرسم المتأثر في برنامج Bitmap (أو ImageBitmap) خارج الشاشة ثم رسم النتيجة. ويحتفظ باقي واجهة المستخدم بمسار تسريع الأجهزة.
نصائح
يمكن أن يؤدي التبديل إلى الرسومات الثنائية الأبعاد المتسارعة بواسطة الأجهزة إلى زيادة الأداء على الفور، ولكن يجب أن تصمّم تطبيقك لاستخدام وحدة معالجة الرسومات بفعالية من خلال اتّباع هذه الاقتراحات:
- تقليل تعقيد التنسيق وإعادة التركيب
- احرص على أن يكون هيكل التنسيق سطحيًا، وقلِّل عدد عمليات إعادة الإنشاء. تأجيل عمليات قراءة الحالة إلى أضيق نطاق، حتى يعيد التغيير رسم أصغر منطقة ممكنة على سبيل المثال، يمكنك قراءة حالة الحركة داخل
Modifier.graphicsLayer { }بدلاً من نص العنصر القابل للإنشاء. لمزيد من المعلومات، يُرجى الاطّلاع على أداء Jetpack Compose. - تجنُّب العرض الزائد
- لا ترسم الكثير من الطبقات فوق بعضها البعض. أزِل أي عناصر واجهة مستخدم محجوبة تمامًا بعناصر أخرى غير شفافة تقع فوقها. إذا كنت بحاجة إلى رسم عدة طبقات مدمجة فوق بعضها البعض، ننصحك بدمجها في طبقة واحدة. من القواعد الأساسية الجيدة التي يجب اتّباعها مع الأجهزة الحالية عدم رسم أكثر من 2.5 مرة عدد وحدات البكسل على الشاشة لكل إطار (يتم احتساب وحدات البكسل الشفافة في صورة نقطية).
- عدم إنشاء عناصر العرض في طرق الرسم
- من الأخطاء الشائعة إنشاء
PaintأوPathجديد في كل مرة يتم فيها استدعاء طريقة عرض. ويؤدي ذلك إلى إجبار أداة جمع البيانات غير المرغوب فيها على العمل بشكل متكرر، كما يؤدي إلى تجاوز عمليات التخزين المؤقت والتحسينات في مسار الأجهزة. لتجنُّب ذلك، أعِد استخدام عناصرك وعدِّلها:- استخدام الطرق العادية: تستخدم طرق
DrawScopeالعادية (مثلdrawRectوdrawCircle) حاليًا كائناتPaintبشكل متكرّر داخليًا بدون الحاجة إلى تخصيص المطوّر. - التعديل بدلاً من إعادة التخصيص: عند كتابة منطق مخصّص، استخدِم
path.rewindلمحوPathحالي بدلاً من إنشاءPathجديد. - الاحتفاظ بالحالة بكفاءة: داخل عنصر قابل للإنشاء، خصِّص العناصر مرة واحدة باستخدام
remember { Path() }. إذا كنت بصدد إنشاء إضافات معدِّلات مخصّصة قابلة لإعادة الاستخدام، عليك تنفيذModifier.Nodeمخصّص باستخدامDrawModifierNodeلتخصيص الكائنات وإعادة استخدامها بدون التسبّب في تخصيصات جديدة للذاكرة المؤقتة.
- استخدام الطرق العادية: تستخدم طرق
- عدم تعديل الأشكال بشكل متكرّر
- يتم عرض الأشكال والمسارات والدوائر المعقّدة، على سبيل المثال، باستخدام أقنعة النسيج. في كل مرة تنشئ فيها مسارًا أو تعدّله، تنشئ سلسلة معالجة الأجهزة قناعًا جديدًا، وهو ما قد يكون مكلفًا.
- عدم تعديل الصور النقطية بشكل متكرّر
- في كل مرة تغيّر فيها محتوى صورة نقطية، يتم تحميلها مرة أخرى كنسيج لوحدة معالجة الرسومات في المرة التالية التي ترسمها فيها.
- استخدام الإصدار الأولي بحذر
- عند إنشاء عنصر قابل للإنشاء شبه شفاف باستخدام
Modifier.alphaأو واجهات برمجة تطبيقات الصور المتحركة في Compose، يتم عادةً عرضه في مخزن مؤقت خارج الشاشة، ما يؤدي إلى مضاعفة معدل التعبئة المطلوب. لتجنُّب زيادة سعة التخزين المؤقت خارج الشاشة للمحتوى غير المتداخل، اضبطCompositingStrategy.ModulateAlpha. بالنسبة إلى طلبات الرسم الفردية، طبِّق قناة ألفا مباشرةً على أمر الرسم (مثلcolor = Color.Red.copy(alpha = 0.5f)) بدون إنشاء طبقة.