کش و همگام‌سازی داده در توسعه موبایل: چیست، چه استراتژی‌هایی و چگونه کار می‌کند

نویسنده: IT Sectr منتشر شده: 2026-06-19 زمان مطالعه: 12 دقیقه

در توسعه موبایل، کار با داده، کش کردن و همگام‌سازی سه جنبه کلیدی هستند که عملکرد و قابلیت اطمینان برنامه را تعیین می‌کنند. به گفته Google Android Architecture Guide، معماری صحیح مدیریت داده به طور مستقیم بر سرعت پاسخ و تجربه کاربر تأثیر می‌گذارد. الگوی Repository یک نقطه دسترسی واحد به تمام منابع داده فراهم می‌کند.

نکات کلیدی

  • Repository — یک منبع داده واحد که جزئیات پیاده‌سازی Remote و Local Data Source را پنهان می‌کند
  • LRU Cache — الگوریتم کش که با رسیدن به محدودیت، کم‌ترین استفاده شدهٔ اخیر را حذف می‌کند
  • Offline Queue — مکانیزم اجرای تأخیری عملیات هنگامی که دستگاه آفلاین است
  • Conflict Resolution — استراتژی حل تعارضات هنگام همگام‌سازی بین چند دستگاه
  • Schema Migration — فرآیند تغییر امن ساختار پایگاه داده محلی بدون از دست دادن اطلاعات

کار با داده در برنامه‌های موبایل: الگوی Repository و Data Source

الگوی Repository یک رویکرد معماری است که در آن یک کلاس مخزن واحد تمام عملیات داده را مدیریت می‌کند و APIهای REST راه دور و ذخیره‌سازی محلی Room یا SwiftData را انتزاع می‌کند. این روش کار با داده به برنامه اجازه می‌دهد ابتدا اطلاعات را از Memory Cache یا Disk Cache دریافت کند، سپس از شبکه، و زمان پاسخ را کاهش دهد. در توسعه موبایل، Repository به لطف توصیه‌های Google و Apple به استاندارد واقعی تبدیل شده است.

Remote Data Source و Local Data Source

Remote Data Source اطلاعات به‌روز را از سرور از طریق درخواست‌های HTTP فراهم می‌کند. Local Data Source ذخیره‌سازی محلی روی دستگاه است که از طریق Room در Android یا SwiftData در iOS پیاده‌سازی می‌شود. مخزن هر دو منبع را ترکیب می‌کند: ابتدا کش محلی را بررسی می‌کند و در صورت نبود داده، از API راه دور درخواست می‌کند. این سازماندهی مدیریت داده به برنامه اجازه می‌دهد در حالت آفلاین کار کند و بار سرور را کاهش دهد.

مثال Repository در Kotlin

kotlin
class UserRepository(
    private val remoteDataSource: UserRemoteDataSource,
    private val localDataSource: UserLocalDataSource
) {
    suspend fun getUsers(): List<User> {
        localDataSource.getCachedUsers()?.let { return it }
        val users = remoteDataSource.fetchUsers()
        localDataSource.cacheUsers(users)
        return users
    }
}

مثال Repository در Swift

swift
class UserRepository {
    private let remote: UserRemoteDataSource
    private let local: UserLocalDataSource
    
    func getUsers() async throws -> [User] {
        if let cached = await local.getCached() { return cached }
        let users = try await remote.fetch()
        await local.save(users)
        return users
    }
}

کش داده: LRU Cache، Disk Cache و Memory Cache

LRU Cache (Least Recently Used) یک الگوریتم کش است که در آن، با رسیدن به محدودیت، عنصری که بیشترین زمان به آن دسترسی نشده حذف می‌شود. در برنامه‌های موبایل، LRU Cache برای تصاویر، پاسخ‌های API و اشیاء سریالایز شده استفاده می‌شود. کش کردن مناسب داده تعداد درخواست‌های شبکه را کاهش می‌دهد و بارگذاری محتوا را سرعت می‌بخشد. کش در برنامه‌های موبایل یک جزء ضروری برای عملکرد بالا است.

Memory Cache در مقابل Disk Cache

Memory Cache داده را در RAM ذخیره می‌کند — دسترسی بسیار سریع است، اما ظرفیت با اندازه heap برنامه محدود می‌شود. Disk Cache اطلاعات را در سیستم فایل ذخیره می‌کند — کندتر است اما می‌تواند بیشتر نگه دارد و بین جلسات باقی می‌ماند. استراتژی بهینه در توسعه موبایل کش دو سطحی است: Memory Cache برای داده‌های داغ و Disk Cache برای داده‌های سرد. هنگام کار با داده، ابتدا کش سطح اول در حافظه بررسی می‌شود، سپس کش سطح دوم روی دیسک.

مثال پیاده‌سازی LRU Cache

kotlin
class MemoryCache<K, V>(
    private val maxSize: Int = 100
) {
    private val cache = LinkedHashMap<K, V>(0, 0.75f, true)

    fun get(key: K): V? = cache[key]

    fun put(key: K, value: V) {
        if (cache.size >= maxSize) {
            cache.remove(cache.keys.first())
        }
        cache[key] = value
    }
}

استراتژی‌های باطل‌سازی کش

کش TTL (Time To Live) به طور خودکار یک ورودی را پس از بازه زمانی مشخص حذف می‌کند — مناسب برای داده‌های API. باطل‌سازی مبتنی بر رویداد هنگام دریافت اعلان push درباره تغییرات، کش را پاک می‌کند. در برنامه‌های موبایل، انتخاب استراتژی کش به نوع داده بستگی دارد: تصاویر برای مدت طولانی کش می‌شوند، در حالی که خوراک خبری نیاز به باطل‌سازی مکرر دارد. Coil در Android و Kingfisher در iOS قبلاً LRU Cache را برای کار با تصاویر یکپارچه کرده‌اند.

صف آفلاین: Offline Queue و Sync Manager

Offline Queue یک ساختار داده است که عملیات کاربر (ایجاد، به‌روزرسانی، حذف) را در پایگاه داده محلی ذخیره می‌کند هنگامی که دستگاه آفلاین است. وقتی اتصال بازیابی شد، Sync Manager این عملیات را به ترتیب روی سرور اعمال می‌کند. این نوع همگام‌سازی داده تضمین می‌کند که هیچ تغییری در هنگام قطع موقت شبکه از دست نرود. در توسعه موبایل، Offline Queue یک جزء حیاتی برای برنامه‌هایی با اتصالات ناپایدار است.

معماری Offline Queue

صف بر روی یک جدول در Room یا SwiftData ساخته می‌شود با فیلدهای: نوع عملیات، بدنه درخواست JSON، timestamp و وضعیت. Sync Manager یک سرویس پس‌زمینه است که عملیات معلق را پردازش می‌کند، به سرور می‌فرستد، وضعیت را به‌روز می‌کند و ورودی‌های موفق را حذف می‌کند. همگام‌سازی داده از طریق WorkManager در Android یا BGTaskScheduler در iOS حتی پس از راه‌اندازی مجدد دستگاه ادامه می‌یابد. استفاده از Offline Queue همراه با مدیریت داده مناسب تجربه کاربری یکپارچه‌ای را تضمین می‌کند.

مثال Offline Queue در Kotlin

kotlin
@Entity
data class SyncOperation(
    @PrimaryKey val id: Long,
    val endpoint: String,
    val method: String,
    val body: String,
    val createdAt: Long
)

class SyncManager(
    private val dao: SyncOperationDao,
    private val api: ApiService
) {
    suspend fun syncPending() {
        dao.getPendingOperations().forEach { op ->
            try {
                api.execute(op.endpoint, op.method, op.body)
                dao.delete(op.id)
            } catch (e: Exception) {
                // retry on next cycle
            }
        }
    }
}

سیاست تلاش مجدد و مهلت زمانی

عقب‌نشینی نمایی بین تلاش‌های مجدد (1s، 2s، 4s، 8s) از سرور در برابر بار ناگهانی محافظت می‌کند و از تلاش‌های بی‌نهایت جلوگیری می‌کند. محدودیت ۵ تلاش از سرریز صف جلوگیری می‌کند. همگام‌سازی داده در برنامه‌های موبایل با پشتیبانی از idempotency در سمت سرور اجازه تلاش مجدد ایمن را می‌دهد و از تکرار جلوگیری می‌کند. این به ویژه برای تراکنش‌های مالی و سفارش‌ها مهم است.

همگام‌سازی داده: Conflict Resolution و Schema Migration

Conflict Resolution مجموعه‌ای از استراتژی‌ها برای موقعیت‌هایی است که داده‌های یکسان روی دستگاه‌های مختلف به طور همزمان تغییر می‌کنند. همگام‌سازی پایه داده نیاز به انتخاب یک رویکرد دارد: Last-Write-Wins (آخرین نوشتن برنده می‌شود)، نسخه‌بندی (نسخه بالاتر برنده می‌شود) یا حل دستی. در سناریوهای پیچیده، از CRDT (Conflict-Free Replicated Data Types) استفاده می‌شود که همگرایی ریاضی داده‌ها را تضمین می‌کند.

استراتژی‌های حل تعارض

Last-Write-Wins ساده‌ترین برای پیاده‌سازی است اما ممکن است تغییرات کاربر را از دست بدهد. Version Vector — هر رکورد یک شماره نسخه و شناسه دستگاه ذخیره می‌کند؛ تعارض زمانی رخ می‌دهد که نسخه‌ها مطابقت ندارند. CRDT قابل‌اعتمادترین اما پیچیده‌ترین استراتژی است: داده‌ها بدون هماهنگ‌کننده متمرکز به صورت ریاضی به یک حالت واحد همگرا می‌شوند. همگام‌سازی داده در برنامه‌های موبایل مبتنی بر CRDT در ویرایش مشترک در Google Docs و همگام‌سازی یادداشت‌های Notion استفاده می‌شود.

Schema Migration: به‌روزرسانی امن پایگاه داده

هنگام به‌روزرسانی برنامه، ساختار پایگاه داده محلی تغییر می‌کند: ستون‌ها، جداول، ایندکس‌ها اضافه می‌شوند. Schema Migration فرآیند تبدیل پایگاه داده موجود به یک طرح جدید بدون از دست دادن داده است. Room از مهاجرت از طریق کلاس Migration با نسخه قدیمی و جدید پشتیبانی می‌کند. SwiftData از VersionedSchema برای توصیف تغییرات استفاده می‌کند. همگام‌سازی داده مناسب بین نسخه‌های برنامه نیاز دارد که مهاجرت‌ها به صورت idempotent آزمایش شوند.

مثال Schema Migration در Room

kotlin
val migration1to2 = object : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("ALTER TABLE users ADD COLUMN avatar_url TEXT")
    }
}

@Database(
    entities = [User::class],
    version = 2
)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

مثال Conflict Resolution در Swift

swift
enum ConflictStrategy {
    case lastWriteWins
    case versionVector
    case crdt
}

struct VersionedDocument {
    let id: String
    let version: Int
    let data: Data
    let editedBy: String
    
    func resolve(with remote: VersionedDocument) -> VersionedDocument {
        return version >= remote.version ? self : remote
    }
}

Room و SwiftData برای ذخیره‌سازی محلی

Room کتابخانه Google برای ذخیره‌سازی محلی در Android است که بر روی SQLite ساخته شده و حاشیه‌نویسی برای توصیف پرس‌وجوهای اعلامی فراهم می‌کند. SwiftData فریم‌ورک Apple برای iOS، macOS، watchOS و visionOS است، جانشین Core Data با نحو مختصر Swift Macro. هر دو ابزار وظیفه کار با داده روی دستگاه را حل می‌کنند، اما با رویکردهای متفاوت برای سازماندهی کد. کش در برنامه‌های موبایل اغلب دقیقاً بر روی این فناوری‌ها ساخته می‌شود.

Room: DAO، Entities و Type Converters

Room از حاشیه‌نویسی @Entity برای جداول و @Dao برای پرس‌وجوها استفاده می‌کند. DAO تمام عملیات SQL را با بررسی زمان کامپایل کپسوله می‌کند — خطاهای نحوی SQL قبل از اجرا شناسایی می‌شوند. Type Converter انواع پیچیده (Date, List) را به انواع ابتدایی SQLite تبدیل می‌کند. مدیریت داده مدرن در برنامه‌های Android حول Room + Flow ساخته می‌شود و به‌روزرسانی‌های واکنشی UI را هنگام تغییر کش یا پایگاه داده محلی فراهم می‌کند.

SwiftData: @Model و @Query

SwiftData از ماکرو @Model برای تعریف موجودیت‌ها و @Query برای مشاهده داده استفاده می‌کند. فریم‌ورک به طور خودکار وابستگی‌ها را ردیابی می‌کند و رابط را در تغییرات به‌روز می‌کند. مهاجرت طرح از VersionedSchema استفاده می‌کند که تمام نسخه‌ها را توصیف می‌کند. همگام‌سازی داده بین SwiftData و سرور از طریق یک Sync Manager سفارشی که از طریق @Query در به‌روزرسانی‌ها مشترک می‌شود پیاده‌سازی می‌شود.

مثال مدل در SwiftData

swift
@Model
final class UserModel {
    var id: String
    var name: String
    var email: String
    var updatedAt: Date
    
    init(id: String, name: String, email: String) {
        self.id = id
        self.name = name
        self.email = email
        self.updatedAt = Date()
    }
}

مقایسه Room در مقابل SwiftData

معیارRoomSwiftData
پلتفرمAndroidApple (iOS، macOS، visionOS)
پایهSQLiteSQLite (پشته Core Data)
نحوحاشیه‌نویسی KotlinSwift Macro
مهاجرتکلاس MigrationVersionedSchema
واکنش‌پذیریFlow / LiveDataProperty wrapper @Query
چند پلتفرمفقط Androidفقط Apple

سوالات متداول

LRU Cache چیست؟

LRU Cache یک الگوریتم کش است که با رسیدن به محدودیت، کم‌ترین استفاده شدهٔ اخیر را حذف می‌کند. برای تصاویر و داده‌های API در برنامه‌های موبایل استفاده می‌شود.

Offline Queue چگونه کار می‌کند؟

Offline Queue عملیات کاربر را در پایگاه داده محلی هنگامی که شبکه وجود ندارد ذخیره می‌کند. Sync Manager هنگام بازیابی اتصال آنها را اجرا می‌کند و تحویل تغییرات به سرور را تضمین می‌کند.

Conflict Resolution چیست؟

Conflict Resolution استراتژی حل تعارضات هنگام همگام‌سازی داده است. رویکردهای اصلی: Last-Write-Wins، Version Vector و CRDT برای سیستم‌های توزیع‌شده.

Room یا SwiftData — کدام را انتخاب کنیم؟

برای Android Room را انتخاب کنید — کتابخانه بالغ با بررسی SQL زمان کامپایل. برای iOS — SwiftData با نحو اعلامی. برای پروژه‌های چند پلتفرم، SQLDelight یا Realm مناسب خواهند بود.

چند وقت یکبار همگام‌سازی انجام دهیم؟

همگام‌سازی داده بهینه برای عملیات بحرانی در هر تغییر و برای بقیه هر ۱۵-۳۰ دقیقه در پس‌زمینه است. برای تحویل فوری از اعلان‌های push استفاده کنید.

خلاصه

  • Repository Remote و Local Data Source را ترکیب می‌کند و یک نقطه دسترسی واحد در کار با داده فراهم می‌کند
  • LRU Cache با سیستم دو سطحی Memory + Disk Cache درخواست‌های شبکه را کاهش می‌دهد و بارگذاری محتوا را سرعت می‌بخشد
  • Offline Queue با Sync Manager تحویل تغییرات را در هنگام قطع اتصال موقت تضمین می‌کند
  • Conflict Resolution مبتنی بر Version Vector یا CRDT از از دست رفتن داده در همگام‌سازی موازی جلوگیری می‌کند
  • Schema Migration به‌روزرسانی امن پایگاه داده محلی را بدون از دست دادن داده کاربر تضمین می‌کند
  • Room با DAO و SwiftData با @Model راه‌حل‌های استاندارد برای ذخیره‌سازی محلی در توسعه موبایل هستند
  • رویکرد جامع به کش و همگام‌سازی داده اساس یک برنامه موبایل با عملکرد بالا است

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه