استفاده از حافظه را بهینه کنید

بهینه سازی حافظه برای اطمینان از عملکرد روان، جلوگیری از خرابی برنامه، و حفظ ثبات سیستم و سلامت پلت فرم بسیار مهم است. در حالی که استفاده از حافظه باید در هر برنامه نظارت و بهینه شود، برنامه‌های محتوا برای دستگاه‌های تلویزیونی چالش‌های خاصی دارند که با برنامه‌های اندروید معمولی برای دستگاه‌های دستی متفاوت است.

مصرف زیاد حافظه می تواند منجر به مشکلاتی در رفتارهای برنامه و سیستم شود از جمله:

  • خود برنامه می تواند کند یا کند یا در بدترین حالت کشته شود.
  • خدمات سیستم قابل مشاهده توسط کاربر (کنترل صدا، داشبورد تنظیمات تصویر، دستیار صوتی و غیره) بسیار کند می شوند یا ممکن است اصلاً کار نکنند.
  • اجزای سیستم ممکن است کشته شوند. سپس این مؤلفه‌ها مجدداً راه‌اندازی می‌شوند، و جرقه‌های شدیدی را در مورد منابع ایجاد می‌کنند و مستقیماً بر برنامه پیش‌زمینه تأثیر می‌گذارند.
  • انتقال به راه‌انداز می‌تواند به‌طور قابل‌توجهی به تعویق بیفتد، و برنامه پیش‌زمینه را تا زمانی که انتقال به پایان برسد، بدون واکنش نشان دهد.
  • سیستم ممکن است وارد یک وضعیت بازیابی مستقیم شود ، در حالی که منتظر تخصیص حافظه است، به طور موقت اجرای رشته ها را متوقف می کند. این ممکن است برای هر رشته‌ای مانند رشته اصلی یا رشته‌های مرتبط با کدک اتفاق بیفتد که به طور بالقوه باعث افت فریم صوتی و تصویری و اشکالات رابط کاربری می‌شوند.

ملاحظات حافظه در دستگاه های تلویزیون

دستگاه های تلویزیون معمولاً حافظه کمتری نسبت به تلفن ها یا تبلت ها دارند. برای مثال، پیکربندی که می‌توانیم در تلویزیون ببینیم، 1 گیگابایت رم و وضوح تصویر 1080p است . در عین حال، اکثر برنامه های تلویزیون دارای ویژگی های مشابه هستند. بنابراین اجرای مشابه و چالش های مشترک. این دو وضعیت مشکلاتی را ایجاد می‌کنند که در انواع دستگاه‌ها و برنامه‌های دیگر دیده نمی‌شوند:

  • برنامه های تلویزیونی رسانه معمولاً از هر دو نماهای تصویر شبکه ای و تصاویر پس زمینه تمام صفحه تشکیل شده اند که نیاز به بارگیری تعداد زیادی از تصاویر در حافظه در مدت زمان کوتاهی دارند.
  • برنامه‌های تلویزیونی جریان‌های چندرسانه‌ای را پخش می‌کنند که نیاز به اختصاص مقدار مشخصی از حافظه برای پخش ویدیو و صدا دارند و برای اطمینان از پخش روان به بافرهای رسانه‌ای قابل‌توجهی نیاز دارند.
  • ویژگی‌های رسانه اضافی (جستجو، تغییر قسمت، تغییر آهنگ صوتی، و غیره) اگر به درستی اجرا نشود، می‌تواند فشار بیشتری بر حافظه وارد کند.

دستگاه های تلویزیون را درک کنید

این راهنما در درجه اول بر روی استفاده از حافظه برنامه و اهداف حافظه برای دستگاه های با رم کم تمرکز دارد.

در دستگاه های تلویزیون، این ویژگی ها را در نظر بگیرید:

  • حافظه دستگاه : مقدار حافظه دسترسی تصادفی (RAM) که دستگاه نصب کرده است.
  • وضوح رابط کاربری دستگاه : وضوحی که دستگاه برای ارائه رابط کاربری سیستم عامل و برنامه ها استفاده می کند. این معمولاً کمتر از وضوح تصویر دستگاه است.
  • وضوح ویدیو : حداکثر وضوحی که دستگاه می تواند ویدیوها را با آن پخش کند.

این منجر به دسته بندی انواع دستگاه ها و نحوه استفاده از حافظه توسط آنها می شود.

خلاصه دستگاه های تلویزیون

حافظه دستگاه وضوح تصویر دستگاه وضوح رابط کاربری دستگاه isLowRAMDevice()
1 گیگابایت 1080p 720p بله
1.5 گیگابایت 2160p 1080p بله
≥1.5 گیگابایت 1080p 720p یا 1080p خیر*
≥2 گیگابایت 2160p 1080p خیر*

دستگاه های تلویزیون با رم پایین

این دستگاه‌ها در یک موقعیت با محدودیت حافظه قرار دارند و ActivityManager.isLowRAMDevice() را به true گزارش می‌کنند. برنامه‌هایی که روی دستگاه‌های تلویزیون با RAM پایین اجرا می‌شوند، باید اقدامات کنترل حافظه اضافی را اجرا کنند.

ما دستگاه هایی با ویژگی های زیر را در این دسته قرار می دهیم:

  • دستگاه های 1 گیگابایتی : 1 گیگابایت رم، وضوح 720p/HD (1280x720) رابط کاربری، وضوح تصویر 1080p/FullHD (1920x1080)
  • دستگاه‌های 1.5 گیگابایتی : 1.5 گیگابایت رم، وضوح UI 1080p/FullHD (1920x1080)، وضوح تصویر 2160p/UltraHD/4K (3840x2160)
  • موقعیت های دیگری که در آن OEM پرچم ActivityManager.isLowRAMDevice() را به دلیل محدودیت های حافظه اضافی تعریف می کند.

دستگاه های تلویزیون معمولی

این دستگاه ها از چنین وضعیت فشار حافظه قابل توجهی رنج نمی برند. ما این دستگاه ها را دارای ویژگی های زیر می دانیم:

  • ≥1.5 گیگابایت رم، رابط کاربری 720p یا 1080p و وضوح تصویر 1080p
  • ≥2 گیگابایت رم، رابط کاربری 1080p و وضوح تصویر 1080p یا 2160p

این بدان معنا نیست که برنامه‌ها نباید به استفاده از حافظه در این دستگاه‌ها اهمیت دهند، زیرا برخی سوءاستفاده‌های خاص از حافظه همچنان می‌تواند حافظه موجود را تخلیه کرده و عملکرد ضعیفی داشته باشد.

هدف های حافظه در دستگاه های تلویزیون با رم پایین

هنگام اندازه‌گیری حافظه در این دستگاه‌ها، اکیداً توصیه می‌کنیم هر بخش از حافظه را با استفاده از نمایه‌ساز حافظه Android Studio نظارت کنید. برنامه‌های تلویزیونی باید میزان مصرف حافظه خود را نمایه کنند و دسته‌های خود را زیر آستانه‌هایی که در این بخش تعریف می‌کنیم قرار دهند.

پروفایلر حافظه

در بخش نحوه شمارش حافظه، توضیح مفصلی از ارقام حافظه گزارش شده را خواهید دید. برای تعریف آستانه برای برنامه های تلویزیونی ، ما روی سه دسته حافظه تمرکز خواهیم کرد:

  • Anonymous + Swap : متشکل از جاوا + Native + حافظه تخصیص پشته در Android Studio.
  • گرافیک : به طور مستقیم در ابزار پروفایلر گزارش شده است. به طور کلی از بافت های گرافیکی تشکیل شده است.
  • فایل : به عنوان دسته‌های «کد» + «سایر» در Android Studio گزارش شده است.

با این تعاریف، جدول زیر حداکثر مقداری را که هر نوع گروه حافظه باید استفاده کند را نشان می دهد:

نوع حافظه هدف اهداف استفاده (1 گیگابایت)
ناشناس + تعویض (جاوا + بومی + پشته) برای تخصیص ها، بافرهای رسانه، متغیرها و سایر کارهایی که حافظه فشرده دارند استفاده می شود. <160 مگابایت
گرافیک توسط GPU برای بافت ها و بافرهای مربوط به نمایش استفاده می شود 30-40 مگابایت
فایل برای صفحات کد و فایل های موجود در حافظه استفاده می شود. 60-80 مگابایت

حداکثر حافظه کل (Anon+Swap + Graphics + File) نباید بیشتر از موارد زیر باشد:

  • 280 مگابایت کل حافظه مصرفی ( Anon+Swap + Graphics + File ) برای دستگاه های 1 گیگابایتی با رم کم.

اکیداً توصیه می شود از موارد زیر تجاوز نکنید:

  • 200 مگابایت استفاده از حافظه در ( Anon+Swap + Graphics ).

حافظه فایل

به عنوان راهنمایی کلی برای حافظه پشتیبان فایل، توجه داشته باشید که:

  • به طور کلی حافظه فایل توسط مدیریت حافظه سیستم عامل به خوبی مدیریت می شود.
  • ما در حال حاضر آن را دلیل اصلی فشار حافظه نمی‌دانیم.

با این حال، هنگامی که به طور کلی با حافظه فایل سروکار دارید:

  • کتابخانه های استفاده نشده را در ساخت خود قرار ندهید و در صورت امکان از زیر مجموعه های کوچک کتابخانه ها به جای موارد کامل استفاده کنید.
  • فایل های بزرگ را در حافظه باز نگه ندارید و به محض اینکه کار با آنها تمام شد، آنها را آزاد کنید.
  • اندازه کد کامپایل شده خود را برای کلاس های جاوا و کاتلین به حداقل برسانید ، راهنمای برنامه خود را Shrink، obfuscate و بهینه سازی کنید .

توصیه های تلویزیونی خاص

این بخش توصیه های خاصی را برای بهینه سازی استفاده از حافظه در دستگاه های تلویزیون ارائه می دهد.

حافظه گرافیکی

از فرمت ها و وضوح تصویر مناسب استفاده کنید.

  • تصاویر با وضوح بالاتر از وضوح UI دستگاه بارگیری نکنید. به عنوان مثال، تصاویر 1080p باید به 720p در یک دستگاه رابط کاربری 720p کوچک شوند.
  • در صورت امکان از بیت مپ های سخت افزاری استفاده کنید .
    • در کتابخانه‌هایی مانند Glide، ویژگی Downsampler.ALLOW_HARDWARE_CONFIG را فعال کنید که به‌طور پیش‌فرض غیرفعال است. با فعال کردن این، از تکثیر نقشه‌های بیتی که در غیر این صورت هم در حافظه گرافیکی و هم در حافظه ناشناس وجود دارند، جلوگیری می‌کند.
  • از رندرهای میانی و رندرهای مجدد خودداری کنید
    • اینها را می توان با Android GPU Inspector شناسایی کرد:
    • در بخش «بافت‌ها» به دنبال تصاویری باشید که به‌جای اینکه فقط عناصر تشکیل‌دهنده آن‌ها باشند، گام‌هایی به سوی رندر نهایی هستند، این معمولاً «رندر میانی» نامیده می‌شود.
    • برای برنامه‌های Android SDK، اغلب می‌توانید با استفاده از پرچم طرح‌بندی forceHasOverlappedRendering:false برای غیرفعال کردن رندرهای میانی برای این طرح‌بندی، آنها را حذف کنید.
    • به عنوان یک منبع عالی به اجتناب از همپوشانی رندرها در رندرهای همپوشانی مراجعه کنید.
  • در صورت امکان از بارگذاری تصاویر مکان‌نما خودداری کنید ، @android:color/ یا @color برای بافت‌های مکان‌نما استفاده کنید.
  • هنگامی که ترکیب بندی می تواند به صورت آفلاین انجام شود از ترکیب چندین تصویر روی دستگاه خودداری کنید . ترجیح می‌دهید تصاویر مستقل را به جای انجام ترکیب‌بندی تصویر از تصاویر دانلود شده بارگیری کنید
  • برای مقابله بهتر با بیت مپ، راهنمای Handling bitmaps را دنبال کنید.

حافظه Anon+Swap

Anon+Swap از تخصیص‌های Native + Java + Stack در نمایه‌ساز حافظه Android Studio تشکیل شده است. از ActivityManager.isLowMemoryDevice() برای بررسی اینکه آیا حافظه دستگاه محدود است یا خیر، استفاده کنید و با رعایت این دستورالعمل ها، خود را با این وضعیت وفق دهید.

  • رسانه:
    • بسته به رم دستگاه و وضوح پخش ویدیو، اندازه متغیری را برای بافرهای رسانه تعیین کنید . این باید برای 1 دقیقه پخش ویدیو باشد:
      1. 40-60 مگابایت برای 1 گیگابایت / 1080p
      2. 60-80 مگابایت برای 1.5 گیگابایت / 1080p
      3. 80-100 مگابایت برای 1.5 گیگابایت / 2160p
      4. 100-120 مگابایت برای 2 گیگابایت / 2160p
    • تخصیص حافظه رسانه رایگان هنگام تغییر یک قسمت برای جلوگیری از افزایش مقدار کل حافظه ناشناس.
    • بلافاصله پس از توقف برنامه، منابع رسانه را آزاد کنید و متوقف کنید : برای مدیریت منابع صوتی و تصویری از تماس های چرخه حیات فعالیت استفاده کنید. اگر یک برنامه صوتی نیستید، وقتی onStop() در فعالیت‌های شما اتفاق افتاد، پخش خود را متوقف کنید ، تمام کارهایی را که انجام می‌دهید ذخیره کنید و منابع خود را تنظیم کنید تا منتشر شوند. برای برنامه ریزی کار ممکن است بعداً نیاز داشته باشید. به بخش مشاغل و هشدارها مراجعه کنید.
    • هنگام جستجوی ویدیو به حافظه بافر توجه کنید : برنامه‌نویسان اغلب زمانی که به دنبال آماده‌سازی ویدیو برای کاربر هستند، 15 تا 60 ثانیه از محتوای آینده را اختصاص می‌دهند، اما این باعث ایجاد سربار حافظه اضافی می‌شود. به طور کلی، تا زمانی که کاربر موقعیت ویدیویی جدید را انتخاب نکرده است، بیش از 5 ثانیه از بافر آینده استفاده نکنید. اگر در حین جستجو به شدت نیاز دارید که زمان بیشتری را از قبل بافر کنید، مطمئن شوید:
      • بافر جستجو را از قبل تخصیص دهید و دوباره از آن استفاده کنید.
      • اندازه بافر نباید بزرگتر از 15-25 مگابایت باشد (بسته به حافظه دستگاه).
  • تخصیص ها:
    • از راهنمای حافظه گرافیکی استفاده کنید تا مطمئن شوید که تصاویر را در حافظه ناشناس تکرار نمی کنید
      • تصاویر اغلب بزرگترین کاربر حافظه هستند، بنابراین تکرار آنها می تواند فشار زیادی بر دستگاه وارد کند. این امر به ویژه در هنگام ناوبری سنگین در نمای شبکه ای تصویر صادق است.
    • تخصیص‌ها را با حذف ارجاع‌ها هنگام حرکت صفحه‌ها منتشر کنید : مطمئن شوید که هیچ ارجاعی به بیت مپ و اشیاء باقی نمانده است.
  • کتابخانه ها:
    • هنگام افزودن کتابخانه های جدید، تخصیص حافظه از کتابخانه ها را نمایه کنید ، زیرا ممکن است کتابخانه های اضافی را نیز بارگیری کنند، که ممکن است تخصیص هایی را نیز ایجاد کند و Binding ایجاد کند.
  • شبکه سازی:
    • در هنگام راه‌اندازی برنامه، تماس‌های شبکه را مسدود نکنید ، آنها زمان راه‌اندازی برنامه را کاهش می‌دهند و در هنگام راه‌اندازی، حافظه اضافی ایجاد می‌کنند، جایی که حافظه به‌ویژه توسط بارگذاری برنامه محدود می‌شود. ابتدا یک صفحه در حال بارگذاری یا اسپلش نشان داده و پس از برقراری رابط کاربری درخواست های شبکه را انجام دهید.

اتصالات

Binding ها سربار حافظه اضافی را معرفی می کنند زیرا برنامه های کاربردی دیگر را به حافظه می آورند یا مصرف حافظه برنامه محدود شده را افزایش می دهند (اگر قبلاً در حافظه باشد) تا تماس API را تسهیل کند. در نتیجه، حافظه موجود برای برنامه پیش‌زمینه کاهش می‌یابد . هنگام اتصال یک سرویس، به زمان و مدت استفاده از صحافی توجه داشته باشید. مطمئن شوید که صحافی را به محض اینکه لازم نیست آزاد کنید .

الزام‌آوری‌های معمول و بهترین شیوه‌ها:

  • Play integrity API : برای بررسی یکپارچگی دستگاه استفاده می شود
    • یکپارچگی دستگاه را بعد از بارگیری صفحه و قبل از پخش رسانه بررسی کنید
    • قبل از پخش محتوا، ارجاع به PlayIntegrity StandardIntegrityManager را منتشر کنید.
  • کتابخانه صورت‌حساب Play : برای مدیریت اشتراک‌ها و خریدها با استفاده از Google Play استفاده می‌شود
    • کتابخانه را پس از صفحه بارگیری راه‌اندازی کنید و قبل از پخش هر رسانه، تمام کارهای صورت‌حساب را مدیریت کنید.
    • هنگامی که با استفاده از کتابخانه تمام شد و همیشه قبل از پخش ویدیو یا رسانه، از BillingClient.endConnection() استفاده کنید.
    • از BillingClient.isReady() و BillingClient.getConnectionState() استفاده کنید تا بررسی کنید که آیا سرویس قطع شده است یا خیر، در صورت نیاز به انجام مجدد هر کار صورتحساب، و سپس BillingClient.endConnection() پس از اتمام دوباره انجام دهید.
  • GMS FontsProvider
    • ترجیح دهید از فونت‌های مستقل در دستگاه‌های با رم کم به جای استفاده از ارائه‌دهنده فونت‌ها استفاده کنید، زیرا دانلود فونت‌ها پرهزینه است و FontsProvider خدمات را برای انجام آن ملزم می‌کند.
  • کتابخانه Google Assistant : گاهی اوقات برای جستجو و جستجوی درون برنامه ای استفاده می شود، در صورت امکان، این کتابخانه را جایگزین کنید.
    • برای برنامه‌های leanback : از متن Gboard به گفتار یا کتابخانه androidx.leanback استفاده کنید.
    • برای برنامه های Compose :
      • برای پیاده سازی جستجوی صوتی از نوشتار به گفتار Gboard استفاده کنید.
    • Watch Next را پیاده سازی کنید تا محتوای رسانه ای در برنامه شما قابل شناسایی باشد.

خدمات پیش زمینه

خدمات پیش زمینه نوع خاصی از خدمات است که به یک اعلان گره خورده است. این اعلان در سینی اعلان در تلفن‌ها و تبلت‌ها نمایش داده می‌شود، اما دستگاه‌های تلویزیونی سینی اعلان به همان معنای آن دستگاه‌ها ندارند. حتی اگر خدمات پیش زمینه مفید باشند زیرا می توان آنها را در حالی که برنامه در پس زمینه است در حال اجرا نگه داشت، برنامه های تلویزیون باید این دستورالعمل ها را دنبال کنند:

در Android TV و Google TV، خدمات پیش زمینه فقط زمانی مجاز به ادامه کار هستند که کاربر برنامه را ترک کند:

  • برای برنامه‌های صوتی : سرویس‌های پیش‌زمینه تنها زمانی مجاز به ادامه کار هستند که کاربر برنامه را ترک کند تا آهنگ صوتی را ادامه دهد. سرویس باید بلافاصله پس از پایان پخش صدا متوقف شود.
  • برای هر برنامه دیگری: پس از خروج کاربر از برنامه شما، همه خدمات پیش زمینه باید متوقف شوند ، زیرا هیچ اعلانی برای اطلاع دادن به کاربر مبنی بر اینکه برنامه همچنان در حال اجرا است و منابع مصرف می کند وجود ندارد.
  • برای کارهای پس زمینه مانند به روز رسانی توصیه ها یا تماشای بعدی ، از WorkManager استفاده کنید.

مشاغل و آلارم ها

WorkManager پیشرفته‌ترین API اندروید برای زمان‌بندی کارهای تکراری پس‌زمینه است. WorkManager از JobScheduler جدید در صورت در دسترس بودن (SDK 23+) و AlarmManager قدیمی زمانی که موجود نیست استفاده خواهد کرد. برای بهترین شیوه انجام کارهای برنامه ریزی شده در تلویزیون، این توصیه ها را دنبال کنید:

  • از استفاده از API های AlarmManager در SDK 23+، به ویژه AlarmManager.set() , AlarmManager.setExact() و روش های مشابه خودداری کنید ، زیرا به سیستم اجازه نمی دهند زمان مناسب برای اجرای کارها را تعیین کند (به عنوان مثال، زمانی که دستگاه بیکار است).
  • در دستگاه‌های با رم کم، از اجرای کارها اجتناب کنید، مگر اینکه به شدت ضروری باشد. در صورت نیاز، از WorkManager WorkRequest فقط برای به‌روزرسانی توصیه‌ها پس از پخش استفاده کنید و سعی کنید تا زمانی که برنامه هنوز باز است این کار را انجام دهید.
  • Constraints WorkManager را تعریف کنید تا به سیستم اجازه دهید کارهای شما را در زمان مناسب اجرا کند:

کاتلین

Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresStorageNotLow(true)
.setRequiresDeviceIdle(true)
.build()

جاوا

Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresStorageNotLow(true)
.setRequiresDeviceIdle(true)
.build()
  • اگر باید کارها را به طور منظم اجرا کنید (مثلاً برای به روز رسانی Watch Next بر اساس فعالیت تماشای محتوای کاربر در برنامه خود در دستگاه دیگری)، پس مصرف حافظه را پایین نگه دارید و مصرف حافظه کار را زیر 30 مگابایت نگه دارید.

سایر دستورالعمل های عمومی

دستورالعمل های زیر اطلاعات کلی در مورد توسعه برنامه Android ارائه می دهد:

  • تخصیص اشیاء را به حداقل برسانید، استفاده مجدد از شی را بهینه کنید و هر شی بلااستفاده را فوراً حذف کنید.
    • از ارجاع به اشیا، به خصوص بیت مپ ها خودداری کنید .
    • از استفاده از System.gc() و فراخوانی‌های حافظه مستقیم خودداری کنید زیرا در فرآیند مدیریت حافظه سیستم تداخل دارند: به عنوان مثال، در دستگاه‌هایی که از zRAM استفاده می‌کنند، تماس اجباری به gc() می‌تواند به طور موقت استفاده از حافظه را به دلیل فشرده‌سازی و رفع فشرده‌سازی افزایش دهد. حافظه
    • از LazyList مانند نمایش داده شده در مرورگر کاتالوگ در Compose یا RecyclerView در جعبه ابزار Leanback UI که اکنون منسوخ شده است برای استفاده مجدد از نماها و عدم ایجاد مجدد عناصر لیست استفاده کنید.
    • عناصر حافظه پنهان محلی از ارائه دهندگان محتوای خارجی خوانده می شوند که بعید است تغییر کنند و فواصل به روز رسانی را تعریف کنند که از تخصیص حافظه خارجی اضافی جلوگیری می کند.
  • نشت احتمالی حافظه را بررسی کنید.
    • مراقب موارد نشت حافظه معمولی مانند ارجاعات درون رشته های ناشناس، تخصیص مجدد بافرهای ویدیویی که هرگز منتشر نمی شوند و سایر موقعیت های مشابه باشید.
    • از heap dump برای رفع اشکال نشت حافظه استفاده کنید.
  • برای به حداقل رساندن مقدار کامپایل به موقع مورد نیاز هنگام اجرای برنامه خود در شروع سرد، پروفایل های پایه ایجاد کنید.

خلاصه ابزار