Android Kotlin:如何将MovieItem存入SharedPreferences并在收藏Fragment展示
完整电影收藏持久化实现流程
一、持久化方案选择
对于轻量的收藏列表,SharedPreferences是简单高效的选择(如果后续需要复杂查询或大数据量,可切换为Room数据库)。我们将收藏的MovieItem序列化为JSON数组,存入SharedPreferences实现持久化。
二、前置准备:确保可序列化
首先确认Image类也支持Gson序列化(实现Serializable或确保所有字段可被Gson解析):
data class Image( @SerializedName("medium") val mediumUrl: String?, @SerializedName("original") val originalUrl: String? ): Serializable // 必须实现Serializable,或确保字段都是基本类型/可序列化类型
三、详情页收藏逻辑(DetailViewModel)
实现添加/取消收藏、判断收藏状态的核心逻辑,直接操作SharedPreferences:
class DetailViewModel : ViewModel() { private val gson = Gson() private val sharedPref = ApplicationProvider.getApplicationContext<Context>() .getSharedPreferences("MovieFavorites", Context.MODE_PRIVATE) // 添加收藏(自动去重) fun addToFavorites(movie: MovieItem) { // 读取已有收藏列表 val existingJson = sharedPref.getString("favorites_list", "[]") val favorites = gson.fromJson(existingJson, Array<MovieItem>::class.java).toMutableList() // 根据id去重,避免重复收藏 if (!favorites.any { it.id == movie.id }) { favorites.add(movie) // 保存更新后的列表 val updatedJson = gson.toJson(favorites) sharedPref.edit().putString("favorites_list", updatedJson).apply() } } // 取消收藏 fun removeFromFavorites(movieId: Int) { val existingJson = sharedPref.getString("favorites_list", "[]") val favorites = gson.fromJson(existingJson, Array<MovieItem>::class.java).toMutableList() favorites.removeAll { it.id == movieId } val updatedJson = gson.toJson(favorites) sharedPref.edit().putString("favorites_list", updatedJson).apply() } // 判断当前电影是否已收藏(用于切换详情页按钮状态) fun isMovieFavorite(movieId: Int): Boolean { val existingJson = sharedPref.getString("favorites_list", "[]") val favorites = gson.fromJson(existingJson, Array<MovieItem>::class.java).toList() return favorites.any { it.id == movieId } } }
四、收藏列表读取与状态管理(FavoritesViewModel)
用LiveData暴露收藏列表,让Fragment自动感知数据变化:
class FavoritesViewModel : ViewModel() { private val gson = Gson() private val sharedPref = ApplicationProvider.getApplicationContext<Context>() .getSharedPreferences("MovieFavorites", Context.MODE_PRIVATE) // 对外暴露不可变的LiveData,内部用MutableLiveData更新 private val _favoritesList = MutableLiveData<List<MovieItem>>() val favoritesList: LiveData<List<MovieItem>> = _favoritesList // 初始化时加载收藏列表 init { loadFavorites() } // 加载收藏列表 fun loadFavorites() { val favoritesJson = sharedPref.getString("favorites_list", "[]") val favoritesArray = gson.fromJson(favoritesJson, Array<MovieItem>::class.java) _favoritesList.value = favoritesArray.toList() } // 手动刷新列表(比如从详情页返回时调用) fun refreshFavorites() { loadFavorites() } }
五、收藏Fragment展示逻辑
观察ViewModel的LiveData,自动更新RecyclerView:
class FavoritesFragment : Fragment() { private lateinit var viewModel: FavoritesViewModel private lateinit var recyclerView: RecyclerView private lateinit var movieAdapter: MovieAdapter // 复用原有的MovieItem适配器 override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_favorites, container, false) recyclerView = view.findViewById(R.id.recycler_favorites) // 初始化适配器,传入空列表 movieAdapter = MovieAdapter(emptyList()) recyclerView.apply { adapter = movieAdapter layoutManager = LinearLayoutManager(context) } return view } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel = ViewModelProvider(this)[FavoritesViewModel::class.java] // 观察收藏列表变化,自动更新UI viewModel.favoritesList.observe(viewLifecycleOwner) { movies -> movieAdapter.updateData(movies) } } // 回到前台时刷新列表,确保数据最新 override fun onResume() { super.onResume() viewModel.refreshFavorites() } }
六、适配器优化
给MovieAdapter添加数据更新方法,推荐用DiffUtil提升性能:
class MovieAdapter(private var movies: List<MovieItem>) : RecyclerView.Adapter<MovieAdapter.MovieViewHolder>() { // ... 你的ViewHolder实现和绑定逻辑 // 简单更新(如果数据量小) fun updateData(newMovies: List<MovieItem>) { movies = newMovies notifyDataSetChanged() } // 推荐:用DiffUtil优化更新,避免全量刷新 fun updateDataWithDiff(newMovies: List<MovieItem>) { val diffResult = DiffUtil.calculateDiff(MovieDiffCallback(movies, newMovies)) movies = newMovies diffResult.dispatchUpdatesTo(this) } // DiffCallback实现 private class MovieDiffCallback( private val oldList: List<MovieItem>, private val newList: List<MovieItem> ) : DiffUtil.Callback() { override fun getOldListSize() = oldList.size override fun getNewListSize() = newList.size override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) = oldList[oldItemPosition].id == newList[newItemPosition].id override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = oldList[oldItemPosition] == newList[newItemPosition] } }
七、常见问题修正
- 你之前的
getFavorites方法存在变量重名问题,且错误使用MovieItem.class(Kotlin中应使用MovieItem::class.java) - 仅转换JSON而不保存到持久化介质,重启后数据会丢失,必须将JSON写入SharedPreferences或数据库
内容的提问来源于stack exchange,提问作者FenLM
相关产品推荐
相关产品推荐

