You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于MVP模式多视图共享Repository持久化数据的实现方案

Great question! The core idea you've outlined in your Repository class is absolutely valid for reusing data across multiple presenters—you just need to tweak the implementation to ensure the data persists correctly across View1 and View2's lifecycles. Let's break this down step by step.

Is your initial Repository code feasible?

Yes, but with a critical adjustment. Your current code defines a private list and a getData() method to populate it, but creating a new Repository instance for each presenter would mean each gets a fresh, empty list. To share data between Presenter1 and Presenter2, your Repository needs to be a single instance (singleton) so both presenters work with the same underlying data store.

Here's a refined, thread-safe singleton version of your Repository for in-memory caching:

class Repository private constructor() {
    // Use thread-safe collections if modifying from background threads
    private val list = mutableListOf<YourDataType>()
    @Volatile private var isDataLoaded = false

    // Singleton instance (thread-safe lazy initialization)
    companion object {
        val instance: Repository by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            Repository()
        }
    }

    suspend fun getData(): List<YourDataType> {
        if (!isDataLoaded) {
            // Replace with your actual data fetch logic (network/local)
            val fetchedData = fetchDataFromSource()
            list.clear()
            list.addAll(fetchedData)
            isDataLoaded = true
        }
        // Return an immutable copy to prevent external modification of internal state
        return list.toList()
    }

    private suspend fun fetchDataFromSource(): List<YourDataType> {
        // Simulate network delay/data fetch
        delay(1000)
        return listOf(YourDataType("Item 1"), YourDataType("Item 2"))
    }
}

// Example data class for your content
data class YourDataType(val name: String)

How to keep the list persistent across View1 and View2 lifecycles?

The solution depends on whether you need data to survive only while the app is running, or persist through app restarts.

1. In-memory persistence (app session only)

If you only need data to stay available as long as the app is active (no need to survive force closes or restarts), the singleton approach above is sufficient:

  • Both Presenter1 and Presenter2 will access the same Repository.instance, so once View1 loads the data into the list, Presenter2 can immediately retrieve it without re-fetching.
  • Thread safety reminder: If getData() uses asynchronous operations (like network calls), use thread-safe collections (e.g., CopyOnWriteArrayList) or synchronize access to the list to avoid race conditions. The @Volatile flag on isDataLoaded ensures all threads see the latest state of this flag.

2. Persistent local storage (survives app restarts)

For data that needs to persist even if the app is killed, extend the Repository to include local caching. Popular options are Room (for structured data), SharedPreferences (for small key-value sets), or file storage. Here's how to integrate Room:

First, define your Room entities and DAO:

// Room Entity
@Entity
data class YourDataType(
    @PrimaryKey val id: String,
    val name: String
)

// Room DAO
@Dao
interface YourDataDao {
    @Query("SELECT * FROM YourDataType")
    suspend fun getAll(): List<YourDataType>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAll(items: List<YourDataType>)
}

// Room Database
@Database(entities = [YourDataType::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun yourDataDao(): YourDataDao

    companion object {
        // Singleton database instance
        val instance: AppDatabase by lazy {
            Room.databaseBuilder(
                context, // Pass your app context here
                AppDatabase::class.java,
                "app_database"
            ).build()
        }
    }
}

Then update the Repository to use both in-memory and local caching:

class Repository private constructor(
    private val yourDataDao: YourDataDao
) {
    private val list = mutableListOf<YourDataType>()
    @Volatile private var isDataLoaded = false

    companion object {
        val instance: Repository by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            Repository(AppDatabase.instance.yourDataDao())
        }
    }

    suspend fun getData(): List<YourDataType> {
        if (!isDataLoaded) {
            // First check local storage for cached data
            val localData = yourDataDao.getAll()
            if (localData.isNotEmpty()) {
                list.clear()
                list.addAll(localData)
                isDataLoaded = true
                return list.toList()
            }
            // No local data? Fetch from network and cache locally
            val fetchedData = fetchDataFromSource()
            list.clear()
            list.addAll(fetchedData)
            yourDataDao.insertAll(fetchedData)
            isDataLoaded = true
        }
        return list.toList()
    }

    private suspend fun fetchDataFromSource(): List<YourDataType> {
        // Replace with actual network request logic
        delay(1000)
        return listOf(YourDataType("1", "Item 1"), YourDataType("2", "Item 2"))
    }
}

With this setup:

  • View1 triggers getData(): the Repository checks local storage first, fetches from the network if needed, then saves data to both memory and local storage.
  • View2's Presenter calls getData(): it gets the in-memory list immediately (if already loaded by View1), or falls back to local storage if the app was restarted.

Key Takeaways

  • Singleton Repository: The foundation for sharing data across presenters—ensures all components use the same data source.
  • Caching Strategy: Choose in-memory only for temporary data, or combined in-memory + local storage for persistent data.
  • Thread Safety: Always handle asynchronous operations carefully to avoid race conditions in data access.

内容的提问来源于stack exchange,提问作者MaaAn13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:24:55