Kotlin如何实现跨页面SharedPreferences存储IBAN数据并列表展示
IBAN存储应用两个核心问题修复方案
一、修复AddIbanActivity保存数据覆盖历史的问题
- 根因:页面启动时直接初始化了空的
ibanList,没有提前读取SharedPreferences中已经存储的历史IBAN数据,每次保存都是把仅包含当前新录入条目的列表写入,直接覆盖旧数据。 - 修复逻辑:页面初始化时,先从SharedPreferences读取已存的IBAN列表JSON,反序列化为
ArrayList<IbanModel>赋值给ibanList,没有历史数据时再使用空列表。
修改后的AddIbanActivity完整代码如下:
package com.example.ibansfer import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.example.ibansfer.databinding.ActivityAddIbanBinding import com.example.ibansfer.models.IbanModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken class AddIbanActivity : AppCompatActivity() { private lateinit var binding: ActivityAddIbanBinding private var ibanList: ArrayList<IbanModel> = ArrayList() private val gson = Gson() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityAddIbanBinding.inflate(layoutInflater) setContentView(binding.root) setTitle("IBAN bilgisi ekle") supportActionBar?.setDisplayHomeAsUpEnabled(true) val sharedPreferences = getSharedPreferences("ibans", MODE_PRIVATE) // 初始化时先读取历史存储的列表 val savedJson = sharedPreferences.getString("ibans", null) if (!savedJson.isNullOrEmpty()) { val type = object : TypeToken<ArrayList<IbanModel>>() {}.type ibanList = gson.fromJson(savedJson, type) } binding.ibanSaveBttn.setOnClickListener { val ibanOwner = binding.ibanOwner.text.toString().trim() val bankName = binding.bankName.text.toString().trim() val ibanAdress = binding.ibanAdress.text.toString().trim() if (ibanOwner.isEmpty() || bankName.isEmpty() || ibanAdress.isEmpty()) { Toast.makeText(this, "Lütfen tüm alanları doldurunuz.", Toast.LENGTH_LONG).show() } else { ibanList.add(IbanModel(ibanOwner, bankName, ibanAdress)) // 保存最新列表 val editor = sharedPreferences.edit() val newJson = gson.toJson(ibanList) editor.putString("ibans", newJson) editor.apply() Toast.makeText(this, "IBAN bilgileri başarıyla eklendi.", Toast.LENGTH_LONG).show() finish() } } } override fun onSupportNavigateUp(): Boolean { finish() return true } }
上述代码额外补充了左上角返回按钮的逻辑,同时对输入内容做了首尾空格过滤,避免用户输入全空格的无效内容。
二、首页读取IBAN列表并渲染展示
- 实现逻辑:
- 首页使用
RecyclerView作为列表容器,编写对应Adapter绑定IBAN条目数据 - 在
onResume生命周期中读取SharedPreferences里的最新IBAN列表——从AddIbanActivity返回首页时会触发onResume,可以保证每次看到的都是最新数据 - 把读取到的列表提交给Adapter,刷新列表展示
- 首页使用
步骤1:编写列表条目布局
在layout目录下新建item_iban.xml作为单个IBAN条目的布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp" android:layout_margin="8dp" android:background="@android:color/white" android:elevation="2dp"> <TextView android:id="@+id/tvIbanOwner" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:textStyle="bold"/> <TextView android:id="@+id/tvBankName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:textSize="14sp"/> <TextView android:id="@+id/tvIbanAddress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:textSize="14sp" android:textColor="@android:color/darker_gray"/> </LinearLayout>
步骤2:编写RecyclerView适配器
新建IbanListAdapter.kt处理列表数据和视图的绑定:
package com.example.ibansfer import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.example.ibansfer.databinding.ItemIbanBinding import com.example.ibansfer.models.IbanModel class IbanListAdapter(private val ibanList: List<IbanModel>) : RecyclerView.Adapter<IbanListAdapter.IbanViewHolder>() { inner class IbanViewHolder(val binding: ItemIbanBinding) : RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IbanViewHolder { val binding = ItemIbanBinding.inflate(LayoutInflater.from(parent.context), parent, false) return IbanViewHolder(binding) } override fun onBindViewHolder(holder: IbanViewHolder, position: Int) { val currentItem = ibanList[position] holder.binding.tvIbanOwner.text = currentItem.ibanOwner holder.binding.tvBankName.text = currentItem.bankName holder.binding.tvIbanAddress.text = currentItem.ibanAdress } override fun getItemCount(): Int { return ibanList.size } }
步骤3:编写首页逻辑
首先修改首页布局activity_main.xml,添加跳转按钮和列表容器:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/btnAddIban" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Yeni IBAN ekle" android:layout_margin="16dp"/> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rvIbanList" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
在首页Activity(默认是MainActivity)中编写数据读取和列表初始化逻辑:
package com.example.ibansfer import android.content.Intent import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.LinearLayoutManager import com.example.ibansfer.databinding.ActivityMainBinding import com.example.ibansfer.models.IbanModel import com.google.gson.Gson import com.google.gson.reflect.TypeToken class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private val gson = Gson() private lateinit var ibanAdapter: IbanListAdapter private var ibanList: ArrayList<IbanModel> = ArrayList() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) // 初始化RecyclerView ibanAdapter = IbanListAdapter(ibanList) binding.rvIbanList.apply { layoutManager = LinearLayoutManager(this@MainActivity) adapter = ibanAdapter } // 跳转到添加IBAN页面 binding.btnAddIban.setOnClickListener { startActivity(Intent(this, AddIbanActivity::class.java)) } } override fun onResume() { super.onResume() // 每次页面回到前台时读取最新的IBAN列表 val sharedPreferences = getSharedPreferences("ibans", MODE_PRIVATE) val savedJson = sharedPreferences.getString("ibans", null) ibanList.clear() if (!savedJson.isNullOrEmpty()) { val type = object : TypeToken<ArrayList<IbanModel>>() {}.type val savedList: ArrayList<IbanModel> = gson.fromJson(savedJson, type) ibanList.addAll(savedList) } // 通知适配器刷新列表 ibanAdapter.notifyDataSetChanged() } }
注意:保证
IbanModel的字段名和录入属性一一对应,同时确认模块级build.gradle中已经引入Gson和RecyclerView的依赖,否则代码会编译失败。
内容的提问来源于stack exchange,提问作者onur_dev
相关产品推荐
相关产品推荐

