مدیریت کارآمد وضعیت وب ویو، مدیریت کارآمد وضعیت وب ویو

هنگام مدیریت چرخه حیات یک برنامه اندروید، حفظ وضعیت کاربر در طول بازیابی منابع پس‌زمینه، جزء اصلی یک تجربه کاربری یکپارچه است. برای برنامه‌هایی که شامل گردش‌های کاری وب هستند، WebView.saveState(Bundle) به شما امکان می‌دهد تاریخچه ناوبری و وضعیت یک WebView را در یک Bundle سریالایز کنید. این داده‌ها متعاقباً می‌توانند با استفاده از WebView.restoreState(Bundle) بازیابی شوند.

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

محدودیت تراکنش ۱ مگابایتی و پاک کردن وضعیت

اندروید محدودیت ۱ مگابایتی را برای کل حجم داده‌هایی که می‌توانند در savedInstanceState ذخیره شوند، اعمال می‌کند. این بودجه ۱ مگابایتی در کل فرآیند برنامه به اشتراک گذاشته می‌شود. اگر یک برنامه شامل چندین نمونه WebView باشد، وضعیت ناوبری جمعی و تاریخچه آنها باید در این تخصیص مشترک واحد جای گیرد. تجاوز از این مرز باعث ایجاد خطای TransactionTooLargeException می‌شود که منجر به خرابی برنامه می‌شود.

یک استراتژی رایج اما مشکل‌ساز برای کاهش خطرات، شامل نظارت بر اندازه‌ی بسته‌ی وضعیت WebView و پاک کردن کامل تاریخچه‌ی WebView در صورت عبور از یک آستانه‌ی ایمنی دلخواه (مانند ۳۰۰ کیلوبایت) است. اگرچه این کار از خرابی جلوگیری می‌کند، اما باعث ایجاد پسرفت‌های شدیدی در تجربه‌ی کاربر می‌شود:

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

  • بی‌اعتبارسازی BFCache : پاک کردن تاریخچه مانع از استفاده برنامه از Back-Forward Cache (BFCache) می‌شود و امکان رندر فوری صفحات بازدید شده قبلی را از بین می‌برد.

  • افزایش تأخیر : کاربران وضعیت فعلی خود را در WebView از دست می‌دهند و نیاز به پیمایش کامل و مقداردهی اولیه مجدد دارند. این فرآیند به طور قابل توجهی سربار شبکه و تأخیر تراکنش را افزایش می‌دهد.

استراتژی‌های کاهش ریسک معماری

برای جلوگیری از خرابی‌های TransactionTooLargeException بدون کاهش تجربه کاربری از طریق حذف کامل تاریخچه، باید تعادل دقیقی بین حفظ وضعیت و کارایی حافظه برقرار کنید. با پیاده‌سازی استراتژی‌های بهینه‌سازی زیر، می‌توانید با خیال راحت بودجه تراکنش ۱ مگابایتی را مدیریت کنید و در عین حال تاریخچه ناوبری ضروری و یکپارچگی جلسه را حفظ کنید.

اعمال محدودیت‌های اندازه در سریال‌سازی وضعیت

به جای پاک کردن کامل پشته ناوبری وقتی که خیلی بزرگ می‌شود، یک الگوی مؤثرتر، کوتاه کردن داده‌های تاریخی است:

  • سیاست حذف هدفمند : از WebViewCompat.saveState() برای سریالی کردن وضعیت (state) در حین اعمال محدودیت بایت خاص (برای مثال، WebViewCompat.saveState(webView, outState, maxSizeBytes) ) استفاده کنید. این API به طور خودکار ورودی‌های ناوبری قدیمی‌تر را به ترتیب حذف می‌کند تا زمانی که کل بار مفید (payload) در تخصیص تعریف شده شما قرار گیرد. نکته مهم این است که این کار فقط Bundle سریالی شده را بدون تغییر یا پاک کردن تاریخچه زنده WebView فعال، کوتاه می‌کند و تضمین می‌کند که ناوبری فوری رو به عقب کاملاً دست نخورده باقی می‌ماند.

  • حذف ورودی‌های رو به جلو : اگر رابط کاربری برنامه یک دکمه بازگشت ارائه می‌دهد اما فاقد یک دکمه اختصاصی برای ناوبری رو به جلو است، می‌توانید با تنظیم پارامتر includeForwardState از API saveState به false ، تمام ورودی‌های ناوبری رو به جلو را حذف کنید. این کار به طور قابل توجهی حجم payload را بدون تأثیر بر مسیرهای ناوبری موجود کاربر کاهش می‌دهد.

مدیریت تأخیر منابع با HTTP Cache Quota API

در حالی که saveState محدودیت ۱ مگابایتی Bundle برای تاریخچه ناوبری موقت مدیریت می‌کند، HTTP Cache Quota API کنترل دستی بر منابع وب پایدار (حافظه پنهان دیسک) را بر اساس هر پروفایل ارائه می‌دهد. این امر تمایز روشنی بین زمینه ناوبری کوتاه‌مدت و دارایی‌های ذخیره‌شده بلندمدت ایجاد می‌کند.

انتخاب سهمیه مناسب شامل یک بده بستان عملکردی است:

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

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

پیاده‌سازی زیر نحوه پیکربندی سهمیه حافظه پنهان دیسک برای پروفایل پیش‌فرض را نشان می‌دهد:

کاتلین

if (WebViewFeature.isFeatureSupported(WebViewFeature.MULTI_PROFILE) &&
    WebViewFeature.isFeatureSupported(WebViewFeature.HTTP_CACHE)) {
    val defaultProfile = ProfileStore.getInstance()
        .getOrCreateProfile(Profile.DEFAULT_PROFILE_NAME)
    val httpCache = defaultProfile.httpCache

    // Set explicit cache size to 50MB (50 * 1024 * 1024 bytes)
    httpCache.setQuotaBytes(50L * 1024 * 1024)
}

جاوا

if (WebViewFeature.isFeatureSupported(WebViewFeature.MULTI_PROFILE) &&
    WebViewFeature.isFeatureSupported(WebViewFeature.HTTP_CACHE)) {
    Profile defaultProfile = ProfileStore.getInstance()
        .getOrCreateProfile(Profile.DEFAULT_PROFILE_NAME);
    HttpCache httpCache = defaultProfile.getHttpCache();

    // Set explicit cache size to 50MB (50 * 1024 * 1024 bytes)
    httpCache.setQuotaBytes(50L * 1024 * 1024);
}

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

ملاحظات کلیدی عملکرد

نکات زیر محدودیت‌های فنی و رفتارهای داخلی داده‌ها را که بر رفتار حالت WebView حاکم هستند، برجسته می‌کند:

  • حباب‌های مبهم PageState : تقریباً 70٪ از داده‌های ذخیره شده توسط saveState شامل حباب‌های داخلی PageState از موتور رندر است. این داده‌ها حالت‌های جلسه جزئی، از جمله ورودی‌های فرم و موقعیت‌های اسکرول iframe را ثبت می‌کنند. از تلاش برای تجزیه دستی یا حذف بخش‌های جداگانه از این حباب‌ها خودداری کنید، زیرا انجام این کار خطرات امنیتی شدیدی را ایجاد می‌کند و یکپارچگی بازیابی جلسه را از بین می‌برد.

  • مدیریت دقیق تاریخچه : API استاندارد WebBackForwardList به طور پیش‌فرض از حذف دلخواه عناصر تاریخچه به صورت جداگانه پشتیبانی نمی‌کند. برای مدیریت دقیق وضعیت، باید استراتژی‌های کوتاه‌سازی را با استفاده از پارامترهای maxSizeBytes و includeForwardState در WebViewCompat.saveState() پیاده‌سازی کنید تا ایمنی معماری تضمین شود.