دليل شامل للغاية لمكتبات Android التي لا تستخدم بشكل كافٍ

نشرت: 2022-03-11

سيخبرك أي مطور متمرس أن أفضل كود لديه ليس رمزًا كتبوه. إنه رمز أخذوه من عمل شخص آخر.

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

Android ليس استثناء. المصدر النهائي لإعادة استخدام الكود هو Android SDK نفسه ، والذي يأتي مع تركيبات وخدمات رائعة ستؤدي الكثير من عملك نيابة عنك.

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

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

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

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

اختيار مكتبة Android الصحيحة

عند اختيار مكتبة ، أبحث عن أربع ميزات رئيسية:

  • يوفر حلاً متسقًا وعالي الجودة لمشكلة حقيقية وغير تافهة.
  • يستخدم واجهة برمجة تطبيقات بسيطة قدر الإمكان.
  • لا يفرض أي تغييرات في هندسي العام.
  • لديه قاعدة مستخدمين كبيرة ويفضل مجتمع مطور نشط.

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

مكتبات Android

اجتازت المكتبات التي أغطيها أدناه جميع الاختبارات الأربعة. كما أنها تحل بعض أكثر الجوانب تحديًا في تطوير الأجهزة المحمولة.

  • مكتبتان لحقن التبعية ، ربط التخطيط بجافا ، كائنات وهمية.
  • نموذج المراسلة العامة / الفرعي داخل التطبيق.
  • طبقة اتصالات HTTP آمنة وفعالة وذاتية الاسترداد.
  • معالجة الصور: التنزيل والتخزين المؤقت وتغيير الحجم والتحميل في ذاكرة الوصول العشوائي.
  • دفق الفيديو في الوقت الحقيقي.
  • كشف تسرب الذاكرة.

ButterKnife: أداة حقن التبعية المطلقة

هذه هي مكتبة حقن التبعية النهائية لنظام Android. بسيطة وقوية وسريعة للغاية (بدون انعكاس!) وقادرة على التخلص من الكثير من التعليمات البرمجية المعيارية لتطبيقك.

قد يجادل البعض بأن ButterKnife هو ما يجب أن يكون عليه تخطيط Android لرسم خرائط Java في المقام الأول.

حقن الاعتماد على الروبوت Butterknife

لقد ولت الحاجة إلى ربط كل من طرق العرض الخاصة بك مباشرةً عبر مكالمة للبحث عن findViewById() ؛ بدلاً من ذلك ، هناك عرض توضيحي يمنحك وصولاً مباشرًا إلى الكود. كما يلغي برنامج ButterKnife أيضًا الحاجة إلى أحداث واجهة المستخدم المعيارية مثل onClick و onTouch وما إلى ذلك ، ويستبدلها برمز يتم حقنه تلقائيًا.

لكن يكفي الدردشة ، دعنا نرى الكود.

عرض ربط الحقل:

 class MyButterKnifeActivity extends Activity { @BindView(R.id.name) TextView name; @BindView(R.id.address) TextView address; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_activity); ButterKnife.bind(this); // MUST BE CALLED BEFORE ACCESSING UI FIELDS name.setText(“etc etc”); } }

مورد ملزم:

 class ExampleActivity extends Activity { @BindString(R.string.username) String username; @BindDrawable(R.drawable.graphic) Drawable graphic; @BindColor(R.color.bg_color) int bgColor; @BindDimen(R.dimen.lower_padding) Float lowerPadding; // and no need for getResources().getString()/getDrawable/getColor() }

ربط حدث واجهة المستخدم:

 @OnClick(R.id.my_button) public void clickHandler(View view) { // onClick logic goes here }

تعليقات Android: أخذ حقن التبعية إلى المستوى التالي

في المرتبة الثانية بعد ButterKnife عندما يتعلق الأمر بحقن التبعية ، تستخدم AndroidAnnotations أسلوبًا مختلفًا قليلاً: الفئات التي يتم إنشاؤها تلقائيًا ، والتي بمجرد أن تحصل على تعليق منها ، تكون بسيطة للغاية. والأكثر فائدة هو أنه يسمح لك بحقن التبعية "استنادًا إلى الاسم". على سبيل المثال ، @ViewById ListView myUserList; يوجه المكتبة لتعيين هذا الحقل مع layoutListView بنفس الاسم.

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

لكن قدرات حقن AndroidAnnotations تذهب إلى أبعد من ذلك. يمكنك إدخال كل من الحالة والتخطيط في نشاط ما.

تطبيق AndroidAnnotations:

 @NoTitle @Fullscreen @EActivity(R.layout.my_layout) public class MyActivity extends Activity { @ViewById ListView customerList; // auto-binded to R.id.customerList @App MyApplication app; // auto-binded to app object @AminationRes Animation fadeoutAnimation; @UiThread void updateUI() { // main thread action } }

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

 new Handler(Looper.getMainLooper()).post(new Runnable() { logic goes here } ); // NO ANNOTATIONS

في AndroidAnnotations ، كل ما عليك فعله هو التعليق على وظيفتك باستخدامUiThread ، وهو الآن مضمون للتنفيذ دائمًا:

 @UiThread void updateUI() {..} // WITH ANNOTATIONS

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

هنا ، يأتي AndroidAnnotations بمفهوم جديد ، وهو مفهوم EBean . كل ما عليك فعله هو تحديد صفك على هذا النحو باستخدام @EBean ، وأنت على ما يرام:

 @EBean public class MyNonComponentClass { @SystemService NotificationManager notifManager; @Bean MyOtherClass dependency; @UiThread void updateUI() { // main thread work goes here } }

EventBus: تسهيل الاتصال عبر المكونات

تحول مكتبة EventBus المشكلة التي لطالما طاردت مطوري Android إلى نزهة في الحديقة. لم يكن الاتصال عبر المكونات أبسط من أي وقت مضى - استخدم نموذج حانة / فرعي بسيط للتواصل بين أي جزئين من نظامك.

الرسوم المتحركة EventBus

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

لم تعد خدمة الاستطلاع في الخلفية بحاجة إلى أن تكون على دراية بأجزاءك لإطعامها بأحداث التغيير.

استخدام EventBus واضح ومباشر.

أ. إنشاء فئات الحدث. العمل مع POJOs هو الأفضل هنا:

 class NewUserEvent { String fullname; String address; String role; // add getters and setters }

ب. إنشاء طرق معالجة الأحداث في الفصل — أي فئة ترغب في الاشتراك في هذه الأحداث:

 class MySubscriber { @Subscribe public void newUserHandler(NewUserEvent event) { // handle NewUserEvent } @Subscribe public void newUserHandler(AnotherEvent event) { // handle AnotherEvent } }

لكن مهلاً ، سيتوقف أي مطور Android نصف متمرس ويسأل عند هذه النقطة: ما هو نموذج سلاسل العمليات لهؤلاء المعالجات؟ وهل يمكنني إجبار معالج على الخروج من الخيط الرئيسي ، على سبيل المثال ، إذا كان يتضمن الوصول إلى مكون واجهة المستخدم؟ سؤال جيد…

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

 @Subscribe(threadMode = ThreadMode.MAIN) public void runOnMainThreadHandler(AnotherEvent event) { … }

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

ج. قم بإدارة دورة حياة التسجيل في EventBus لفئة المشترك الخاصة بك - أي ، متى يتم الاتصال ومتى يتم قطع الاتصال بالناقل؟ سيكون تدفق التسجيل المعقول للنشاط على النحو التالي:

 class MySubscriberActivity extends Activity { @Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); // START RECEIVING EVENTS HERE } @Override public void onStop() { EventBus.getDefault().unregister(this); // NO MORE EVENTS super.onStop(); } }

ما ورد أعلاه ، بالطبع ، مجرد مثال. يمكنك إجراء التسجيل (un) في أي مكان تختاره.

د. وأخيرًا ، أطلق حدثًا فعليًا:

 EventBus.getDefault().post(new MyEvent(“I'm here”));

هناك الكثير الذي يجب معرفته حول استخدام EventBus: أحداث البث المتعدد (السلوك الافتراضي) ، واستخدام الأحداث الثابتة ، وسلاسل التسليم ، والأولويات ، والمزيد. لكن ما ورد أعلاه كافٍ لتبدأ بهذه التقنية البسيطة والقوية.

OkHttp: HttpClient Android على المنشطات

هذه هي الطريقة التي يجب أن تتم كتابة HttpClient على نظام Android. بسيط جدا ، ذكي جدا. تهتم مكتبة OkHttp داخليًا بحلقة إعادة المحاولة ، وضغط الحمولة التلقائي ، ودعم Http / 2 ، وتجميع الاتصال ، والتخزين المؤقت للاستجابة حتى تتمكن من تجنب الوصول غير الضروري إلى الشبكة.

OkHttp مكتبة الرسوم المتحركة

استخدام OkHttp غير منطقي.

مشاركة HTTP:

 OkHttpClient client = new OkHttpClient(); MediaType JSON = MediaType.parse("application/json; charset=utf-8"); RequestBody body = RequestBody.create(JSON, json_str); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); return response.body().string();

الحصول على HTTP:

 OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(urls[0]) .build(); Response responses = client.newCall(request).execute(); String jsonData = responses.body().string();

يدعم OkHttp أيضًا ميزات مفيدة مثل الشبكات غير المتزامنة وطلب استعلام مسار إعادة التوجيه واستعلام ذاكرة التخزين المؤقت المحلية والمزيد. لا تتردد في استخدامها عند الحاجة. يستخدم معظم المطورين OkHttp كبديل أكثر ذكاءً لعميل HTTP الافتراضي في Android ، HttpURLConnection. في الواقع ، بدأ هذا المشروع بأكمله كشوكة خاصة لـ HttpURLConnection.

أنا أحب قوتها - فهي تضيف على الفور إلى طبقة الشبكة الخاصة بك.

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

بيكاسو: هناك سبب وجيه لاستخدام Google له أيضًا!

بيكاسو هو أبسط وأقوى طريقة لإدارة تنزيل الصور والتخزين المؤقت وتغيير الحجم والقص.

هذا البيان:

 Picasso.with(context).load(url).resize(50,50).centerCrop().into(imageView)

سأفعل هذا من أجلك:

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

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

مكتبة بيكاسو أندرويد للرسوم المتحركة

حسنًا ، في جهاز Android العادي ، لا يحصل التطبيق على أكثر من 50 إلى 60 ميغا بايت من ذاكرة الوصول العشوائي ، وعامل البكسل إلى البايت لمعظم أجهزة Android هو 4. وهذا يعني محاولة تحميل صورة بدقة 13 ميغا بكسل من بطاقة SD يتطلب 52 ميغا بايت من ذاكرة الوصول العشوائي. بمعنى آخر ، سيتعطل تطبيقك على الفور.

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

أحد أقوى الأدلة على قوة هذه المكتبة: تستخدم العديد من عينات أكواد Android الخاصة بشركة Google من العامين الماضيين بيكاسو لتحميل الصور.

ActiveAndroid: ORM Sans Performance Overhead

أصبح ORM ، اختصارًا لرسم الخرائط العلائقية للكائن ، شائعًا في أيام J2EE. يسمح لك بتخزين POJOs الخاصة بك واستردادها من قاعدة بيانات دون الحاجة إلى تحويلها إلى حقول منفصلة.

ActiveAndroid ORM

هل هو مفيد؟ إلى حد كبير ، لأنه يسمح لك بكتابة جزء كبير من تطبيقك دون ترميز أي عبارة SQL.

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

لا توجد عبارات SQL مشفرة يدويًا ، ولا توجد نفقات إضافية في الأداء!

استعمال:

أ. التهيئة في كائن التطبيق عن طريق توسيع فئة تطبيق مخصصة:

 public class MyApplication extends extends com.activeandroid.app.Application { … }

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

 @Table(name = "Categories") public class UserDetails extends Model { @Column(name = "Name") public String name; @Column(name = "Address") public String address; @Column(name = "Age") public int age; }

إذا كنت ترغب في تعيين فهرس لأحد الأعضاء ، فاستخدم التعليق التوضيحي التالي:

 @Column(name = "ID", index = true) public String userID;

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

 <meta-data android:name="AA_MODELS" android:value=“com.myapp.MyModelA, com.myapp.MyModelB" />

ملاحظة: لن يتم التعرف على فئات النماذج التي لا تظهر في هذه القائمة بواسطة ActiveAndroid.

د. الكتابة إلى قاعدة البيانات:

 UserDetails usr = new UserDetails(); usr.save(); // RUNS ON A BACKGROUND THREAD

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

 ActiveAndroid.beginTransaction(); try { for (UserDetails u: userList) item.save(); ActiveAndroid.setTransactionSuccessful(); } finally { ActiveAndroid.endTransaction(); }

ه. قراءة POJOs من قاعدة البيانات:

 new Select() .from(UserDetails.class) .where("name = ?", usr.getName()) .orderBy("Age") .executeSingle();

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

LibStreaming: دفق فيديو غير مؤلم

كان دفق الفيديو في الوقت الفعلي يمثل مشكلة كبيرة بسبب واجهات برمجة التطبيقات غير الموثقة والاختلافات في إصدارات SDK واستخدام الانعكاس والمزيد.

مكتبة libStreaming للرسوم المتحركة

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

باختصار ، إنه يبسط تدفق الفيديو.

لاستخدامه مع H.264 و AAC ، عليك القيام بما يلي:

أ. قم بتهيئة كائن جلسة في طريقة onCreate لنشاطك الرئيسي. تمثل كائنات الجلسة تدفق الوسائط إلى نظير:

 protected void onCreate(Bundle savedInstanceState) { mSession = SessionBuilder.getInstance() .setCallback(this) .setSurfaceView(mSurfaceView) .setPreviewOrientation(90) .setContext(getApplicationContext()) .setAudioEncoder(SessionBuilder.AUDIO_NONE) .setAudioQuality(new AudioQuality(16000, 32000)) .setVideoEncoder(SessionBuilder.VIDEO_H264) .setVideoQuality(new VideoQuality(320,240,20,500000)) .build(); mSurfaceView.getHolder().addCallback(this); }

ب. ابدأ الجلسة بالفعل:

 mSession.setDestination(destination_server_url); mSession.start();

ج. أوقف الجلسة عند الانتهاء:

 mSession.stop();

الآن ، من فضلك لا تسيء الفهم. يعد البث في الوقت الفعلي فوضويًا بطبيعته ولا يزيل libStreaming هذا التعقيد. ومع ذلك ، فإنه يقوم بعمل جيد حقًا في إخفاءه عنك في معظم الأوقات. في بعض الحالات ، ستحتاج إلى التعامل مع التعقيد ، على سبيل المثال عند تحديد سياسة إشارات الأقران ، أو اختيار تشفير الكاميرا (عادةً ما تريد استخدام MediaCodec / السطح إلى المخزن المؤقت) ، أو التعامل مع الحزم.

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

يدعم LibStreaming معظم أجهزة التشفير التي تستخدمها تطبيقات Android ، بما في ذلك H.264 و H.263 و AAC و AMR.

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

LeakCanary: كشف تسرب الذاكرة في سطر من التعليمات البرمجية

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

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

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

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

أحيانًا يكون تسريب إشارة إلى نشاط فردي كثيف الموارد كافيًا لتعطيل تطبيقك مع استثناء " نفاد الذاكرة ".

مكتبة LeakCanary

كيف يمكنك الحماية منهم؟ ابدأ بممارسات الترميز الصارمة ، بالطبع. لكن لسنا جميعًا من مطوري Android ذوي الخبرة ، وحتى المطورين ذوي الخبرة ينسون أحيانًا القواعد.

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

يعد استخدام أداة ذاكرة DDMS طريقة رائعة لمعرفة ما إذا كان تطبيقك يتسرب بمرور الوقت. يجب عليك بالتأكيد استخدامه. ومع ذلك ، لن يخبرك بما يسبب التسرب.

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

لاستخدامه ، ما عليك سوى تهيئة leakCanary باستخدام كائن تطبيقك onCreate() :

 public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); // more initialisations } }

إنتهيت. سوف يقوم LeakCanary بمراقبة تسرب الذاكرة وإرسال إشعار إذا اكتشف أحدها.

يحقق LeakCanary هذا السحر عن طريق الحقن التلقائي لكائن يسمى ActivityRefWatcher في جميع أنشطتك ومراقبة عدد المرجع بعد onDestroy() . لا يمكن أن يعني حساب المرجع> 0 على نشاط مدمر سوى تسرب.

هام: لا يعمل اكتشاف التسريب إلا مع تطبيقات وضع التصحيح. لا تختبر أبدًا التسريبات (حسنًا ، ليس مع LeakCanary) في وضع الإصدار APK.

ولكن ماذا لو كنت أرغب في اختبار أجزاء أخرى من نظامي للتأكد من عدم وجود تسريبات؟ هنا ، يقدم LeakCanary كائنًا يسمى refWatcher ، وهو في الواقع القيمة المعادة لاستدعاء التهيئة:

 refWatcher = LeakCanary.install(this);

يمكن استخدامه لمشاهدة القيم التي سيتم استعادتها قريبًا. بتعبير أدق ، القيم التي أعتقد أنه سيتم استعادتها قريبًا. للقيام بذلك ، اتصل على:

 refWatcher.watch(my_soon_to_be_reclaimed_obj);

ستخبرك المكتبة إذا لم يتم تحرير هذا الكائن بعد وقت قصير من مكالمة الساعة.

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

ملخص

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

للتلخيص ، إليك ما يمكن أن يفعله اختياري من مكتبات Android من أجلك:

  • ButterKnife - ستساعدك الشفرة التي تم حقنها تلقائيًا على التخلص من الكثير من التعليمات البرمجية المعيارية لتطبيقك. إنه حقن الكود النهائي لنظام Android. أحتاج أن أقول المزيد؟

  • AndroidAnnotations - استخدم الفئات السريعة المُنشأة تلقائيًا وحقن الشفرة المستند إلى الاسم لتوفير الوقت دون أي عقوبة على الأداء على المنطق المشفر يدويًا.

  • EventBus - فصل المكونات للحصول على كود أكثر قوة ، لم يكن الاتصال عبر المكونات أبسط من أي وقت مضى.

  • OkHttp - بديل ذكي لـ HttpURLConnection ، مع دعم الشبكات غير المتزامنة وطلب استعلام مسار إعادة التوجيه واستعلام ذاكرة التخزين المؤقت المحلية والمزيد.

  • بيكاسو - معالجة مبسطة للصور جيدة جدًا تستخدمها Google الآن. إنها توفر الوقت بشكل كبير في المشاريع الإعلامية الضخمة وبعض المشاريع القديمة.

  • ActiveAndroid - أصبح ORM سهلاً بدون أي زيادة في الأداء.

  • LibStreaming - دفق الفيديو في الوقت الفعلي ، تستخدمه تطبيقات البث الرئيسية.

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

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

الموضوعات ذات الصلة: Android 7.0 للمطورين: ميزات جديدة وترقيات في الأداء وأشياء أخرى لن تهتم بها