iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 18
0
自我挑戰組

Kotlin Everyday:新手寫程式踩的坑系列 第 18

Day 18 ─用 Kotlin 做待辦清單 Todolist(2) SharedPreferences 中篇

  • 分享至 

  • xImage
  •  

昨天介紹了 SharedPreferences 用法,並且將傳送 Intent 變成儲存 local storage 的動作,今天就要來把資料讀出來、並且把它放入 RecycleView 裡面:

1. 取得 SharedPreferences 資料

還記得我們之前有定義 Thing 這種資料嗎?而 things 是存放 Thing 這種型態的陣列

data class Thing(val todo: String)       //MyAdapter.kt

private var things = ArrayList<Thing>()  //MainActivity.kt

之前我們是把傳過來的資料 getExtras 取得值,把值丟入 things 這個陣列後讓 Adpater 更新畫面,讓值可以在 RecycleView 呈現。
現在全部註解掉,我們要改的是取值的方式---從 SharedPreferences 取值

// val todo = data?.extras?.getString("todo")
// things.add(Thing(todo!!))
// adapter.notifyDataSetChanged()    //全部註解掉

寫一個 getData 函式
打開之前儲存時命名 save 的 SharedPreferences 文件,將裡面的內容用 key 值取出來,存為 Thing 這種資料型態,因為之前有定義陣列 things 存放的就是該資料類型,所以把取出來的資料丟給 things 陣列:

  • key:想取出資料的代碼
  • defValue:如果沒找到資料時要返回的預設值
data class Thing(val todo: String)       
private var things = ArrayList<Thing>() 
...
...
fun getData(){
    val sharedPreferences = getSharedPreferences("save", Activity.MODE_PRIVATE)
    val todo = Thing(sharedPreferences.getString("todo", "")!!)
    things.add(todo)
    adapter.notifyDataSetChanged()
}

當 function 寫好後,在返回動作和初始時都要執行它,這樣回到主頁的畫面才會更新到:

//返回畫面
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
            
            getData()  //返回後也要執行畫面更新
        }
}
//初始畫面
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    getData()  //初始畫面要執行
    
    adapter = MyAdapter(things)
    recycleview.layoutManager = LinearLayoutManager(this)
    recycleview.adapter = adapter
}

現在做完,一切看起來很完美.....除了一件事!!跳出去 APP 之後,之前寫的值是有存下來,可是只存到了最後一項,這是為什麼呢?

因為儲存的時候,key 值每個都是寫 todo ,一個 key 值只能對應一個 value 值,所以 SharedPreferences 文件的 value 會不停被新的 value 覆蓋,因為他們的 key 值是一樣的

editor.putString("todo", "${editText2.text}")

要想辦法讓 key 值變化,設一個 i 值並用迴圈跑,當儲存資料的次數是未知時,可以使用 while 來判斷:

  • 初始值 i = 0,而todo-${i} --- key值
  • while 迴圈用法:根據指定的條件式來判斷是否執行迴圈
while (條件式) {
    迴圈執行的工作
}
var i = 0      
while (!sharedPreferences.getString("todo-${i}", "").isNullOrEmpty()){
    i++
}

條件設成:當某個 key 值 todo-${i} 對應的 value 不為空時,就執行 i++,白話意思是當這個 todo-${i} 被使用過,就跑下一個 i 來當 key值

  • 註解掉之前儲存寫入的 code,先給函式一個型態為 String 的參數 → 暫替 value 的值
fun save(todo: String){
    val sharedPreferences = getSharedPreferences("save", Activity.MODE_PRIVATE)
    val editor = sharedPreferences.edit()
    
    // editor.putString("todo", "${editText2.text}")    註解掉
    
    var i = 0      
    while (!sharedPreferences.getString("todo-${i}", "").isNullOrEmpty()){
        i++
    }
    editor.putString("todo-${i}", todo)
    editor.apply()
}

修改過的函式 save 放到點擊事件裡,這時系統會顯示紅底、要求我要填一個參數,所以這邊 val 一個值,將 EditText 輸入的東西指給這個參數

else {
//    val b = Bundle()
//    b.putString("todo", "${editText2.text}")
//    val intent1 = Intent()
//    intent1.putExtras(b)
    val todo = "${editText2.text}"
    save(todo)
    setResult(Activity.RESULT_OK)
    finish()
}

寫完之後查看一下文件 ,可以看到迴圈有跑成功,key 值會照著 todo-${i} 排序下去,確認都有存進本地資料庫裡,明天就要來練習怎麼把這堆 SharedPreferences 資料讀取出來~


上一篇
Day 17 ─用 Kotlin 做待辦清單 Todolist(2) SharedPreferences 上篇
下一篇
Day 19 ─用 Kotlin 做待辦清單 Todolist(3) SharedPreferences 下篇
系列文
Kotlin Everyday:新手寫程式踩的坑30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言