Android端如何离线存储从MySQL获取的JSON数据?
嘿,这个需求我之前做过好多次啦!核心思路就是把从PHP接口拿到的JSON数据本地缓存起来,无网的时候直接读本地缓存就行。给你几个实用的方案,根据你的数据量级选就行:
实现无网络访问缓存数据的方案
1. 用SharedPreferences缓存(适合小体量JSON数据)
如果你的返回数据是比较小的JSON(比如几条简单的列表项、配置信息),用SharedPreferences最省事——它本身就是Android自带的键值对存储,直接把JSON字符串存进去就行,不用搞复杂的数据库。
步骤:
- 网络请求成功后,把返回的JSON字符串存到SP里
- 每次请求前先判断网络状态:有网就请求接口并更新缓存;无网就直接从SP读取缓存的JSON,解析后使用
代码示例:
存储缓存:
// 假设你已经拿到了接口返回的jsonString val sharedPref = getSharedPreferences("DataCache", Context.MODE_PRIVATE) val editor = sharedPref.edit() editor.putString("cached_data", jsonString) editor.apply()
读取缓存:
val sharedPref = getSharedPreferences("DataCache", Context.MODE_PRIVATE) val cachedJson = sharedPref.getString("cached_data", "") if (!cachedJson.isNullOrEmpty()) { // 解析cachedJson为你需要的实体类(这里用Gson举例) val data = Gson().fromJson(cachedJson, YourDataModel::class.java) // 更新UI展示数据 }
网络状态判断工具:
fun isNetworkAvailable(context: Context): Boolean { val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val networkInfo = connectivityManager.activeNetworkInfo return networkInfo != null && networkInfo.isConnected }
2. 用Room数据库缓存(适合结构化/大量数据)
如果你的数据是结构化的列表(比如多条用户信息、商品数据),Room是更好的选择——它是SQLite的官方封装,支持ORM,查询和管理数据更方便,还能直接缓存实体类,不用手动处理JSON解析。
步骤:
- 定义数据实体类并添加Room注解
- 创建Dao接口,定义增删改查方法
- 网络请求成功后,清空旧缓存再插入新数据到Room
- 无网时直接从Room查询数据
代码示例:
实体类:
@Entity(tableName = "user_data") data class UserData( @PrimaryKey val id: Int, val name: String, val email: String )
Dao接口:
@Dao interface UserDao { @Query("SELECT * FROM user_data") suspend fun getAllUsers(): List<UserData> @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertAll(users: List<UserData>) @Query("DELETE FROM user_data") suspend fun clearAll() }
Room数据库单例:
@Database(entities = [UserData::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao companion object { @Volatile private var INSTANCE: AppDatabase? = null fun getDatabase(context: Context): AppDatabase { return INSTANCE ?: synchronized(this) { val instance = Room.databaseBuilder( context.applicationContext, AppDatabase::class.java, "app_database" ).build() INSTANCE = instance instance } } } }
使用逻辑:
// 网络请求成功后更新缓存(在协程中执行) lifecycleScope.launch { val userDao = AppDatabase.getDatabase(context).userDao() userDao.clearAll() userDao.insertAll(yourApiResponseData) } // 无网时读取缓存(在协程中执行) lifecycleScope.launch { val userDao = AppDatabase.getDatabase(context).userDao() val cachedUsers = userDao.getAllUsers() // 更新UI展示缓存数据 }
3. 本地文件存储(适合任意大小的JSON,灵活但需手动管理)
如果不想用SP或Room,也可以直接把JSON字符串写到本地私有文件里——这种方式最灵活,适合任意大小的JSON,但需要自己处理文件读写的异常和缓存更新。
代码示例:
存储缓存:
fun saveJsonToFile(context: Context, jsonString: String, fileName: String) { try { val outputStream = context.openFileOutput(fileName, Context.MODE_PRIVATE) outputStream.write(jsonString.toByteArray()) outputStream.close() } catch (e: IOException) { e.printStackTrace() } }
读取缓存:
fun readJsonFromFile(context: Context, fileName: String): String? { return try { val inputStream = context.openFileInput(fileName) val reader = BufferedReader(InputStreamReader(inputStream)) val stringBuilder = StringBuilder() var line: String? while (reader.readLine().also { line = it } != null) { stringBuilder.append(line) } inputStream.close() stringBuilder.toString() } catch (e: IOException) { e.printStackTrace() null } }
额外注意点
- 缓存更新策略:可以设置缓存过期时间(比如存数据时记录时间,读取时判断是否超过N小时),避免展示过时数据;也可以每次有网请求成功就覆盖旧缓存。
- 网络状态监听:用
ConnectivityManager.NetworkCallback监听网络状态变化,网络恢复时自动更新缓存,提升用户体验。 - 异常处理:读取缓存时要处理JSON解析失败、文件损坏等情况,避免应用崩溃。
内容的提问来源于stack exchange,提问作者Alain
相关产品推荐
相关产品推荐

