52 : اندرويد : جعل ال ListView تنزلق بشكل سلس Making ListView Scrolling Smooth

 

ملاحظة : الموضوع عبارة عن حلقة من حلقات سلسلة برمجة وتطوير اندرويد Android Development

اندرويد :   جعل ال ListView تنزلق بشكل سلس Making ListView Scrolling Smooth 

السلام عليكم ورحمة الله وبركاته

سوف نتعلم في هذا الدرس مايلي :

  1. استخدام مسرى يعمل في الخلفية Use a Background Thread
  2. Hold View Objects in a View Holder

يتوجب ايضا قراءة

لماذا لون قائمتي اسود ؟ امثلة يقوم بها اندرويد Why is my list black? An Android optimization

إن المفتاح الاساسي لكي نجعل انزلاق ال ListView تنزلق بشكل سلس يكمن بأن نحافظ على المسرى الرئيسي للبرنامج (مسرى واجهة المستخدم UI)خاليا من الاجرائيات الثقيلة.

ويجب التأكيد على ان يتم القيام بكل من عمليات النفاذ إلى القرص disk access , النفاذ للشبكة network access , او النفاذ إلى SQL , ضمن مسرى مختلف Thread.

  • لكي تستطيع ان تقوم بفحص حالة تطبيقك, بإمكانك تفعيل StrictMode.

استخدام مسرى يعمل ضمن الخلفية Use a Background Thread

إن استخدام مسرى يعمل ضمن الخلفية background thread  يزيل عبء كبير عن المسرى الاساسي , وبذلك يستطيع المسرى الاساسي ان يركز على العمليات الخاصة برسم واجهة المستخدم drawing the UI.

في معظم الحالات, يشكل استخدام AsyncTask  طريقة بسيطة لانجاز العمل خارج المسرى الاساسي Main thread.

يقوم AsyncTask  بشكل اوتوماتيكي برصف كل طلبات execute()ضمن رتل queue  ويقوم بتنفيذهم بشكل متسلسل.

هذا السلوك هو عبارة عن سلوك عام بالنسبة لاجرائية معينة ,وهذا يعني بانه لا يتوجب عليك ان تقلق حول بناء thread poot  بنفسك , لان AsyncTask   يقوم بادارة هذا العمل بنفسه.

يقوم الترميز البسيط ادناه باستخدام AsyncTask  ليقوم بتحميل صور ضمن مسرى يعمل بالخلفية background thread, ومن ثم يقوم بتطبيق واظهار تلك الصور على واجهة المستخدم فور انتهائه.

كما انه يبين مؤشر يدل على التحميل progress spinner في اماكن الصور ريثما يتم تحميلهم.

// Using an AsyncTask to load the slow images in a background thread
new AsyncTask<ViewHolder, Void, Bitmap>() {
    private ViewHolder v;

    @Override
    protected Bitmap doInBackground(ViewHolder... params) {
        v = params[0];
        return mFakeImageLoader.getImage();
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        super.onPostExecute(result);
        if (v.position == position) {
            // If this item hasn't been recycled already, hide the
            // progress and set and show the image
            v.progress.setVisibility(View.GONE);
            v.icon.setVisibility(View.VISIBLE);
            v.icon.setImageBitmap(result);
        }
    }
}.execute(holder);

انطلاقا من اندرويد 3.0 (API level 11 ), توافرت عدة مزايا اضافية ضمن AsyncTask, واصبح بإمكانك تفعيلها لتعمل ضمن النوى متعددة المعالجات multiple processor cores. بدلا من استدعاء التابع execute(), بإمكانك ان تستدعي التابع executeOnExecutor(), وذلك من اجل تنفيذ عدة طلبات في نفس الوقت , وذلك اعتمادا على النوى المتوافرةavailable cores .

اخفاء اغراض ال view ضمن view holder

Hold View Objects in a View Holder

قد يقوم الكود الخاص بك باستدعاء التابع findViewById()عدة مرات اثناء الانزلاق ضمن ListView, وهذا الامر بدوره قد يؤدي إلى بطىء الاداء.

حتى عندما يعيد ال Adapter  inflated view  بهدف اعادة استخدامه, فإنك لا تزال تحتاج إلى البحث عن العناصر ضمن هذا ال view لتقوم بالتعديل عليهم.

لذلك هنالك طريقة بديلة تغني عن استدعاء التابع findViewById()  عدة مرات , وتكمن عبر استخدام “view holder” Design pattern.

يقوم غرض ViewHolder بتخزين كل مكون من مكونات ال views , ومن ثم يجب خزن ال viewHolder ضمن حقل التاغ الخاص بالتنسيق tag field of the layout(أي  inflatedView.setTag()), وبذلك يصبح بإمكانك ان تنفذ بشكل مباشر لتلك المكونات بدون الحاجة للبحث عنهم بشكل متكرر.

في البداية , انت بحاجة لإنشاء صف class لتحمل فيه مجموعة ال views التي قمت باستخراجها you need to create a class to hold your exact set of views.

على سبيل المثال :

static class ViewHolder {
  TextView text;
  TextView timestamp;
  ImageView icon;
  ProgressBar progress;
  int position;
}

ومن ثم تقوم بملأ ال ViewHolder وتخزنه ضمن التنسيق.

Then populate the ViewHolder and store it inside the layout.

ViewHolder holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
holder.text = (TextView) convertView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);
holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner);
convertView.setTag(holder);

الان اصبح بإمكان ان تنفذ لكل view  من تلك ال view بدون الحاجة إلى البحث عنه في كل مرة , وبذلك توفر عدد قيم من دورات المعالج.

 وإلى لقاء في حلقة قريبة , وإلى ذلك الحين استودعكم الله والسلام عليكم ورحمة الله وبركاته.

Advertisements

, , , , , , ,

  1. أضف تعليق

اترك رد

Please log in using one of these methods to post your comment:

WordPress.com Logo

أنت تعلق بإستخدام حساب WordPress.com. تسجيل خروج   / تغيير )

صورة تويتر

أنت تعلق بإستخدام حساب Twitter. تسجيل خروج   / تغيير )

Facebook photo

أنت تعلق بإستخدام حساب Facebook. تسجيل خروج   / تغيير )

Google+ photo

أنت تعلق بإستخدام حساب Google+. تسجيل خروج   / تغيير )

Connecting to %s

%d مدونون معجبون بهذه: