
در برنامه نویسی اندروید، کار شما با دستگاهی کوچک است که امکانات سخت افزاری محدودی نسبت به یک کامپیوتر خانگی یا یک لپتاپ دارد. Process های سنگینی مثل GUI، و Phone مقداری از حافظهی RAM دستگاهتان را میگیرد و شما فضای کمتری برای استفاده در برنامهی خود در اختیار دارید.
شاید گوشیهای قوی امروز با 3 گیگابایت RAM و پردازندهی 2.3 گیگاهرتز شامل این نگرانی نباشند اما باید در نظر گرفت که برنامهی شما قرار است روی تمام دستگاههای اندرویدی (یا حداقل بیشترشان) بدون مشکل اجرا شود.
برنامههای موفق اندروید معمولا از انیمیشنهای زیبا و گرافیک کاربرپسندی برخوردارهستند، و استفاده از عکس در جاهای مختلف یک اپلیکیشن خوب، دور از انتظار نیست. اما اگر از دید یک برنامه نویس به ظاهر و کارکرد یک اپلیکیشن موفق نگاه کنیم و یک برنامهی Ram Usage Monitor داشته باشیم، میبینیم نهایت اسفادهی آن برنامه از RAM ، به 50 مگابایت هم نمیرسد.
در برنامه نویسی اندروید، بعد از طراحی ظاهر برنامه مهم ترین مسئله، استفادهی بهینه از منابع به خصوص حافظهی RAM است. بدون توجه به این مسئله برنامه شما ممکن از کمتر از 5 دقیقه برای کاربر کار کند و مفید باشد، زیرا بعد از آن یا سرعت برنامهتان به شدت پایین می آید یا به علت کمبود بیش از حد RAM، اندروید برنامه شما را میبندد (Process آن را Kill میکند) بدون توجه به آن که شما در متد onDestroy یا onStop چه چیزهایی نوشته باشید.
چندین المان در برنامه نویسی هستند که از نظر مصرف حافظهی RAM یکی از خط قرمزهای ما محسوب میشوند
- متغیرها و کلاسهایی که خودمان طراحی کردیم
کلاسهایی که برای خواناتر کردن برنامه تان مینویسید احتمالا یکی از چیزهایی ست که باید بعد از اتمام کار، از نظر مصرف RAM بهینه شوند. اگر درون یک حلقه در هر گام، یک شیء از کلاستان میسازید بهتر است راه دیگری را برای اجرا کردن آن قطعه کد انتخاب کنید. درست است که Garbage Collector در اندروید بسیار خوب عمل میکند و شما لازم نیست نگران کلاسهایتان باشید، اما اگر در کلاستان از Bitmap استفاده میکنید، اعتماد کردن به GC کمی ریسک محسوب میشود.
سعی کنید متغیرهایی با طول زیاد به صورت ایستا (static) تعریف نکنید. منظور از متغیرهایی با طول زیاد، چیزهایی نظیر Bitmap است.
- عکس
اگر در برنامهتان از عکس استفاده میکنید (که به احتمال خیلی زیاد استفاده میکنید) چه این عکس به صورت یک resource برای برنامهتان باشد و چه از اینترنت یا حافظهی داخلی بارگذاری شود، یک خطر بسیار جدی برای برنامهتان محسوب میشود. عکس ها به طور بیرحمانهای RAM مصرف میکنند و یکی از اصلی ترین علت خطای out of memory هستند.
سخت ترین کارتان زمانی است که عکس ها را از اینترنت دریافت میکنید و در یک لیست نشان میدهید، در این حالت نه حجم عکس مشخص است، نه تعداد آیتمهایی که کاربر از لیست میتواند ببیند (به علت اندازههای مختلف صفحه نمایش).
اندازهی عکسها باید قبل از نمایش داده شدن در برنامهتان، بسته به ابعاد ImageView (یا هر ابزاری که عکس را با آن نمایش میدهید) کمتر شوند. همچنین باید توجه داشت که در این کم شدن ابعاد، تغییر کیفیت محسوس نداشته باشید.
این روییه چند مرحله و چند پیش زمینه میخواهد که به طور خلاصه به آن ها اشاره میکنیم.
- کاربرد پوشهی values در پوشههای پروژهی خود را بشناسید و حالتهای مختلف این پوشه را در اندازههای مختلف صفحه نمایش و موقعیتهای مختلف پیاده سازی کنید. مثلا values-large برای تبلتهای 7 و 8 اینچی و values-fa برای زمانی که زبان برنامه، فارسی است. در این پوشه فایلی به نام dimens.xml وجود دارد که بهتر است برای تعیین ابعاد ابزارهای مختلف از این فایل استفاده کنید
- صفحهی مربوط به بارگذاری عکسهای حجیم را در سایت توسعه دهندگان اندروید بخوانید.
- کاربرد متدهای کلاس BitmapFactory را بشناسید. متدهایی برای بارگذاری عکس از اینترنت یا حافظه داخلی گوشی در این کلاس وجود دارند که باعث میشوند سر و کار شما به این کلاس زیاد بیفتد.
- اگر عکسی جزء resource برنامه شما محسوب میشود و در پوشه ی drawable قرار دارد، سعی کنید در صورت امکان نسخههای مختلفی از نظر ابعاد برای پوشههای drawable-small، drawable-medium و… قرار دهید.
اگر عکستان قرار است از حافظهی داخلی گوشی بارگذاری شود یا عکسی که توسط دوربین گرفته شده است را میخواهید نمایش دهید، میتوانید با داشتن ابعاد ابزار نمایش دهندهی عکس، از متد Bitmap.createScaledBitmap استفاده کنید، این متد طول و عرض درخواستی شما را میگیرد و ابعاد عکس داده شده را کاهش (یا افزایش) میدهد. اما مشکلی که این متد دارد این است که کیفیت عکس را به شدت پایین میآورد. زیرا بدون انجام نگاشت و عملیات پردازش تصویر، فقط ابعاد عکس را کوچکتر میکند.
راه دیگری برای کاهش ابعاد عکس وجود دارد. برای این کار، در ابتدا باید ابعاد عکس را بگیرید، و با توجه به ابعاد ابزار نمایش دهندهی عکس، متغیر inSampleSize را محاسبه کنید (متدی برای محاسبه در همان صفحهی توسعه دهندگان وجود دارد) برای این کار حتما باید یک شیء از کلاس BitmapFactory.Options بسازید و متغیر inJustDecodeBounds را true قرار دهید. سپس بعد از محاسبهی inSampleSize با مقدار false برای متغیر inJustDecodeBounds اقدام به بارگذاری عکس کنید. مانند قطعه کد زیر :
BitmapFactory.Options opts =newBitmapFactory.Options(); opts.inJustDecodeBounds =true;BitmapFactory.decodeFile(“yourImagePath”, opts); opts.outHeight;//this is the image Height opts.outWidth;//this is the Image Widthint inSampleSize =CalculateInSampleSize(opts, myImageViewHeight, myImageViewWidth); opts.inSampleSize = inSampleSize; opts.inJustDecodeBounds =false;Bitmap scaledBitmap =BitmapFactory.decodeFile(“yourImagePath”, opts);//this is scaled down picture
این متغیر یک عدد مجذور 2 است که کلاس BitmapFactory از آن استفاده میکند تا ابعاد عکس شما را تقسیم بر این متغیر کند. به زبان دیگر، اگر inSampleSize عدد 2 باشد، هر 4 پیکسل از عکس، به 1 پیکسل نگاشت میشود.
با این روش شما میتوانید مطمئن باشید که کیفیت عکس پایین نمیآید. اما محدودیتی که این روش دارد این است که متغیر inSampleSize حتما بایستی عددی مجذور 2 باشد، اگر شما عکسی با عرض 650 میخواهید، ممکن است متغیر inSampleSize با عدد 2 بتواند عرض را به 700 برساند و با عدد 4، عرض این عکس 350 میشود؛ که بیش از حد کوچک است.
پس بهترین راه برای آنکه عکس مورد نظر را دقیقا در ابعادی که میخواهید دریافت کنید این است که از متغیر inSampleSize و متد createScaledBitmap به طور همزمان استفاده کنید.
اما تمام این داستان برای بارگذاری عکس از اینترنت متفاوت است، زیرا قطعا این که یک بار عکس را دریافت کنیم تا فقط ابعاد آن را اندازه بگیریم و برای نمایش آن، یک بار دیگر مجبور باشیم عکس را از سرور بگیریم، اشتباه است.
برای این کار، من از کتابخانههای زیادی استفاده کردم و خودم هم اقدام به نوشتن یک کتابخانه برای دریافت عکس از اینترنت کردم. اما بهترین کتابخانهای که با آن کار کردم و از امکاناتش استفاده کردم، Universal Image Loader بود. امکانات زیادی برای کش کردن، تغییر ابعاد عکس در این کتابخانه وجود دارد که به احتمال زیاد در برنامهتان مورد استفاده قرار میگیرند.
- لیست
لیستها به دلیل اینکه چندین view را به طور همزمان نمایش میدهند میتوانند یکی از خطرات مصرف RAM در برنامه شما باشند. ListView و GridView پر کاربرد ترین ابزارها در این دسته هستند. معمولا از یک customAdapter برای نمایش دادهها در لیست استفاده میشود، در پیاده سازی این Adapter چه از نوع BaseAdapter باشد، چه ArrayAdapter، در متد getView یک متغیر به نام convertView دارید. کار این متغیر، نگه داری آیتمهایی ست که اکنون از دید کاربر خارج شدهاند و ممکن است نیازی به مقادیرشان نداشته باشید. بهتر است جهت ساختن view از این متغیر استفاده کنید و مقادیر آن را با توجه به آیتمی که کاربر آن را میبیند تغییر دهید. با این کار هم حافظهی آن آیتم را آزاد میکنید، هم نیازی به inflate کردن یک view جدید ندارید.
منبع: blog.sariina.com
ثبت یک نظر
آدرس ایمیل شما منتشر نخواهد شد. فیلدهای الزامی مشخص شده اند *
ورود / ثبت نام با حساب گوگل