原文地址:JavaFx ObservableList的使用詳解 | Stars-One的雜貨小窩
最近在研究MVVM模式,發現可以將之前寫的FxRecyclerView控制元件改造一下,便是開始嘗試,嘗試程序中發現了不少坑,但是網上資料不是太全面,這里便寫一篇筆記記錄一下,以供后來者的學習
注:由于本人使用的是TornadoFx來撰寫JavaFx專案,所以本文代碼是使用Kotlin進行撰寫,需要有Kotlin基礎,閱讀前請須知,以免浪費你寶貴的時間
介紹
在MVVM模式火的今天,沒想到之前JavaFx已經早有實作,估計現在市面這些都是玩別人剩下的了
這次也是想到了之前的FxRecyclerView控制元件可以拿MVVM改造一番
網上的資料并不多,僅有少有的一兩篇,無奈之下,只得自己啃著官方檔案,自己摸索,終于是把基本的使用摸清了
ObservableList,正如其名,可觀察的List,它與List一樣,也是個介面(Java的基礎知識了..)
官方簡短介紹:
A list that allows listeners to track changes when they occur.
大意為當資料改變時,ObservableList可以監聽到這些改變,本質上是提供了一個監聽器介面ListChangeListener.Change來進行相關的監聽,
怎么監聽呢?只需要設定監聽器即可
val observableList = observableListOf(0,1,2,3)
observableList.onChange { change ->
while (change.next()) {
when {
change.wasPermutated() -> println("permutated (${change.from} ,${change.to})")
change.wasReplaced() -> println("replace (${change.from} ,${change.to})")
else -> {
when {
change.wasAdded() -> println("add (${change.from} ,${change.to})")
change.wasRemoved() -> println("remove (${change.from} ,${change.to})")
change.wasUpdated() -> println("update (${change.from} ,${change.to})")
}
}
}
}
}
官方的使用中,必須要求我們在監聽之前呼叫next方法,其回傳false表示當前已經是最后一次改變
wasPermutated()這種方法都是回傳的boolean值,當資料發生對應符合的變化,各自對應的方法會回傳true
change.from和change.to兩個屬性在后面提及,這里稍微留意一下
三種監聽型別
從上面的代碼中,我們可以看到有幾個分支條件,每個分支就是資料發生了某種改變,基本的有三種情況:
- List排列順序改變
- List中的資料發生改變(資料更新)
- List的資料添加及洗掉(資料新增或洗掉)
PS:官方檔案說明中,監聽的順序依次為wasPermutated、add/remove、update
下面對這幾種情況進行說明
1.排列更新監聽
順序排列更新,對應的change.wasPermutated(),其回傳值為boolean值,當ObservableList的順序發生變化(即進行了排序操作),此方法就會回傳為true
fun main() {
val observableList = observableListOf(0,1,2,3)
println(observableList)
observableList.onChange { change ->
while (change.next()) {
when {
change.wasPermutated() -> println("permutated (${change.from} ,${change.to})")
change.wasReplaced() -> println("replace (${change.from} ,${change.to})")
else -> {
when {
change.wasAdded() -> println("add (${change.from} ,${change.to})")
change.wasRemoved() -> println("remove (${change.from} ,${change.to})")
change.wasUpdated() -> println("update (${change.from} ,${change.to})")
}
}
}
}
}
observableList.sortBy { it }
println(observableList)
observableList.sortByDescending { it }
println(observableList)
}
對應的輸出結果為:
[0, 1, 2, 3] //源陣列
permutated (0 ,4) //回呼監聽器中的方法
[0, 1, 2, 3] //升序排列
permutated (0 ,4)
[3, 2, 1, 0] //降序排列
2.資料更新監聽(replace)
這里大家可能會有點疑惑,最上面的代碼不是有個wasUpdated()方法嗎,這里怎么標的是replace?
我自己研究的時候,也是很奇怪...官方的那個wasUpdated()方法沒有找到對應的回呼方式,照理說我更新了陣列中的一個資料,這個wasUpdated()應該回傳的是true,但是實際測驗的時候根本沒有,反而是wasReplaced()回傳了true
//上面省略相關代碼...
//JavaFx對應是set(index,element)方法
observableList[1] = 12 //下標為1的物件更新為12
println(observableList)
輸出結果:
[0, 1, 2, 3]
replace (1 ,2)
[0, 12, 2, 3]
3.資料添加與洗掉監聽(add remove)
資料添加和洗掉就和上面同理了,當我們呼叫add()(包括addAll())和remove()方法,對應的wasAdd()和wasRemove()方法就會回傳true
另外,ObservableList提供了兩個List供我們拿到添加的資料和移除的資料
- change.addedSubList 新增的資料串列
- change.removed 被移除的資料串列
補充:from與to
這里大家可能就注意到了change物件的from和to這兩個屬性的區別了
本質上,
ObservableList里面定義的from和to這兩個代表開始下標和結束下標,在資料發生改變的時候,記錄了是哪幾條資料發生了改變,之后提供給我們,我們在ObservableList.change監聽器方法中就可以使用這兩個變數來進行相關的邏輯操作
以下是官方對from的說明:
If wasAdded is true, the interval contains all the values that were added. If wasPermutated is true, the interval marks the values that were permutated. If wasRemoved is true and wasAdded is false, getFrom() and getTo() should return the same number - the place where the removed elements were positioned in the list.
注意重點:如果是資料移除操作,回傳的from和to數值是相同的
ObservableList方法說明
- addAll()
- remove(from,to) 移除[from,to)之間的元素,from是包含,to是不包含的,注意與remove監聽事件回傳的from和to都是相同的
- move(oldIndex,newIndex) 將下標為oldIndex移動至newIndex下標處
補充:移動監聽(move)
之前沒有找到更新的方法,發現了ObservableList有move的方法,沒想到這個在ObservableList中其實是先做remove操作,之后再做add操作
//代碼與上面的一致,已省略
//將下標1的資料移動到下標3的位置
observableList.moveAt(1,3)
println(observableList)
輸出結果:
[0, 1, 2, 3]
remove (1 ,1)
add (3 ,4)
[0, 2, 3, 1]
參考
- JavaFX - 如何處理ObservableList的更改操作_W3Cschool代碼實體
- ListChangeListener.Change (JavaFX 8)
- ObservableList (JavaFX 8)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/254300.html
標籤:Java
上一篇:Java例外處理(例外基本概念)
下一篇:設計模式之享元模式
