تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
يواجه بعض مستخدمي تطبيقك صعوبة في الوصول إلى الإنترنت بشكل متقطع أو لديهم قيود على مقدار المعلومات التي يمكنهم تنزيلها على أجهزتهم. يمكنك تشجيع المستخدمين على التفاعل مع تطبيقك بشكل أكبر من خلال تقليل مقدار البيانات التي يحتاج تطبيقك إلى تنزيلها.
إنّ أبسط طريقة لتقليل عمليات التنزيل هي تنزيل المحتوى الذي تحتاجه فقط. من ناحية البيانات، يعني ذلك تنفيذ واجهات REST API التي تتيح لك تحديد معايير طلب البحث التي تحدّ من البيانات المعروضة باستخدام مَعلمات مثل وقت آخر تعديل.
وبالمثل، عند تنزيل الصور، من الأفضل تقليل حجم الصور من جهة الخادم بدلاً من تنزيل صور بالحجم الكامل ثم تقليل حجمها من جهة العميل.
تخزين استجابات HTTP مؤقتًا
من الأساليب المهمة الأخرى تجنُّب تنزيل بيانات مكرّرة. يمكنك تقليل احتمال تنزيل جزء البيانات نفسه بشكل متكرّر من خلال استخدام التخزين المؤقت. من خلال تخزين بيانات تطبيقك وموارده مؤقتًا، يمكنك إنشاء نسخة محلية من المعلومات التي يحتاج تطبيقك إلى الرجوع إليها. إذا كان تطبيقك يحتاج إلى الوصول إلى المعلومات نفسها عدة مرات خلال فترة زمنية قصيرة، عليك تنزيلها في ذاكرة التخزين المؤقت مرة واحدة فقط.
من المهم تخزين البيانات مؤقتًا بأكبر قدر ممكن من الفعالية لتقليل إجمالي حجم البيانات التي يتم تنزيلها. يجب دائمًا تخزين الموارد الثابتة مؤقتًا، بما في ذلك عمليات التنزيل عند الطلب، مثل الصور بالحجم الكامل، لأطول فترة ممكنة بشكل معقول. يجب تخزين الموارد عند الطلب بشكل منفصل لكي تتمكّن من إفراغ ذاكرة التخزين المؤقت عند الطلب بانتظام لإدارة حجمها.
لضمان ألا يؤدي التخزين المؤقت إلى عرض تطبيقك لبيانات قديمة، استخدِم رموز حالة HTTP والعناوين المناسبة، مثل العنوانَين ETag وLast-Modified. يتيح لك ذلك تحديد الوقت الذي يجب فيه إعادة تحميل المحتوى المرتبط. مثلاً:
Kotlin
// url represents the website containing the content to place into the cache.valconn:HttpsURLConnection=url.openConnection()asHttpsURLConnectionvalcurrentTime:Long=System.currentTimeMillis()vallastModified:Long=conn.getHeaderFieldDate("Last-Modified",currentTime)// lastUpdateTime represents when the cache was last updated.if(lastModified < lastUpdateTime){// Skip update}else{// Parse updatelastUpdateTime=lastModified}
Java
// url represents the website containing the content to place into the cache.HttpsURLConnectionconn=(HttpsURLConnection)url.openConnection();longcurrentTime=System.currentTimeMillis();longlastModified=conn.getHeaderFieldDate("Last-Modified",currentTime);// lastUpdateTime represents when the cache was last updated.if(lastModified < lastUpdateTime){// Skip update}else{// Parse updatelastUpdateTime=lastModified;}
يمكنك ضبط بعض مكتبات الشبكات لتتجاهل رموز الحالة والعناوين هذه تلقائيًا. عند استخدام OkHttp، على سبيل المثال، سيؤدي ضبط دليل ذاكرة التخزين المؤقت وحجمها للعميل إلى تمكين المكتبة من استخدام التخزين المؤقت لبروتوكول HTTP، كما هو موضّح في نموذج الرمز البرمجي التالي:
بعد إعداد ذاكرة التخزين المؤقت، يمكنك عرض طلبات HTTP المخزَّنة مؤقتًا بالكامل مباشرةً من وحدة التخزين المحلية، ما يلغي الحاجة إلى فتح اتصال بالشبكة.
يمكن أن تتحقّق الاستجابات المخزَّنة مؤقتًا بشكل مشروط من مدى حداثتها من الخادم، ما يؤدي إلى إلغاء تكلفة النطاق الترددي المرتبطة بالتنزيل. يتم تخزين الردود غير المخزّنة مؤقتًا في ذاكرة التخزين المؤقت للردود من أجل الطلبات المستقبلية.
يمكنك تخزين البيانات غير الحسّاسة مؤقتًا في دليل ذاكرة التخزين المؤقت الخارجية غير المُدارة باستخدام
Context.getExternalCacheDir().
بدلاً من ذلك، يمكنك تخزين البيانات مؤقتًا في ذاكرة التخزين المؤقت الآمنة المُدارة للتطبيق باستخدام
Context.getCacheDir().
يُرجى العِلم أنّه قد يتم إفراغ ذاكرة التخزين المؤقت الداخلية هذه عندما تكون مساحة التخزين المتاحة في النظام منخفضة.
استخدام مستودع
للحصول على طريقة أكثر تطورًا للتخزين المؤقت، ننصحك باستخدام نمط تصميم Repository. ويشمل ذلك إنشاء فئة مخصّصة تُعرف باسم "مستودع"، وتوفّر تجريدًا لواجهة برمجة التطبيقات (API) لبعض البيانات أو الموارد المحدّدة. قد يجلب المستودع بياناته في البداية من مصادر مختلفة، مثل خدمة ويب بعيدة، ولكنّه يوفّر للمتصلين نسخة مخزّنة مؤقتًا من البيانات في المكالمات اللاحقة. تتيح لك هذه الطبقة من التوجيه غير المباشر توفير استراتيجية تخزين مؤقت قوية خاصة بتطبيقك. لمزيد من المعلومات حول استخدام نمط Repository في تطبيقك، راجِع دليل بنية التطبيق.
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-08-27 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-08-27 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],null,["Some of your app's users have intermittent access to the internet or have limits\non the amount of information they can download onto their devices. You can\nencourage users to interact with your app more often by reducing the amount of\ndata that your app needs to download.\n\nThe most fundamental way to reduce your downloads is to download only what you\nneed. In terms of data, that means implementing REST APIs that allow you to\nspecify query criteria that limit the returned data by using parameters such as\nthe time of your last update.\n\nSimilarly, when downloading images, it's good practice to reduce the size of\nimages server-side, rather than downloading full-sized images that are reduced\non the client.\n\nCache HTTP responses\n\nAnother important technique is to avoid downloading duplicate data. You can\nreduce the likelihood of downloading the same piece of data repeatedly by using\ncaching. By caching your app's data and resources, you create a local copy of\nthe information that your app needs to reference. If your app needs to access\nthe same piece of information multiple times over a short time period, you need\nto download it into the cache only once.\n\nIt's important to cache as aggressively as possible in order to reduce the total\namount of data that you download. Always cache static resources, including\non-demand downloads such as full-size images, for as long as reasonably\npossible. On-demand resources should be stored separately to enable you to\nregularly flush your on-demand cache to manage its size.\n\nTo ensure that your caching doesn't result in your app displaying stale data,\nuse the appropriate [HTTP status codes and\nheaders](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#validating_cached_responses_with_etags),\nsuch as the\n[`ETag`](https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.2)\nand\n[`Last-Modified`](https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.1)\nheaders. This allows you to determine when the associated content should be\nrefreshed. For example: \n\nKotlin \n\n```kotlin\n// url represents the website containing the content to place into the cache.\nval conn: HttpsURLConnection = url.openConnection() as HttpsURLConnection\nval currentTime: Long = System.currentTimeMillis()\nval lastModified: Long = conn.getHeaderFieldDate(\"Last-Modified\", currentTime)\n\n// lastUpdateTime represents when the cache was last updated.\nif (lastModified \u003c lastUpdateTime) {\n // Skip update\n} else {\n // Parse update\n lastUpdateTime = lastModified\n}\n```\n\nJava \n\n```java\n// url represents the website containing the content to place into the cache.\nHttpsURLConnection conn = (HttpsURLConnection) url.openConnection();\nlong currentTime = System.currentTimeMillis();\nlong lastModified = conn.getHeaderFieldDate(\"Last-Modified\", currentTime);\n\n// lastUpdateTime represents when the cache was last updated.\nif (lastModified \u003c lastUpdateTime) {\n // Skip update\n} else {\n // Parse update\n lastUpdateTime = lastModified;\n}\n```\n\nYou can configure some networking libraries to respect these status codes and\nheaders automatically. When using\n[OkHttp](https://square.github.io/okhttp/), for example, configuring\na cache directory and cache size for the client will enable the library to use\nHTTP caching, as shown in the following code sample: \n\nKotlin \n\n```kotlin\nval cacheDir = Context.getCacheDir()\nval cacheSize = 10L * 1024L * 1024L // 10 MiB\nval client: OkHttpClient = OkHttpClient.Builder()\n .cache(Cache(cacheDir, cacheSize))\n .build()\n```\n\nJava \n\n```java\nFile cacheDir = Context.getCacheDir();\nlong cacheSize = 10L * 1024L * 1024L; // 10 MiB\nOkHttpClient client = new OkHttpClient.Builder()\n .cache(new Cache(cacheDir, cacheSize))\n .build();\n```\n\nWith the cache configured, you can serve fully-cached HTTP requests directly\nfrom local storage, eliminating the need to open a network connection.\nConditionally-cached responses can validate their freshness from the server,\neliminating the bandwidth cost associated with the download. Uncached responses\nget stored in the response cache for future requests.\n\nYou can cache non-sensitive data in the unmanaged external cache directory by\nusing\n[`Context.getExternalCacheDir()`](/reference/android/content/Context#getExternalCacheDir()).\nAlternatively, you can cache data in the managed, secure application cache by\nusing\n[`Context.getCacheDir()`](/reference/android/content/Context#getCacheDir()).\nNote that this internal cache may be flushed when the system is running low on\navailable storage.\n| **Note:** Files stored in either cache location are erased when the app is uninstalled.\n\nUse a repository\n\nFor a more sophisticated approach to caching, consider the Repository design\npattern. This involves creating a custom class, known as a Repository, which\nprovides an API abstraction over some specific data or resource. The repository\nmay initially fetch its data from various sources, such as a remote web service,\nbut provides callers with a cached version of the data in subsequent calls. This\nlayer of indirection allows you to provide a robust caching strategy that's\nspecific to your app. For more information about using the Repository pattern\nwithin your app, see the [Guide to app\narchitecture](/jetpack/guide)."]]