Asynchronous 树视图的异步加载
嘿,我对treeview异步加载数据非常陌生。我正在从rest端点加载类别,我想在那里显示 似乎没有直接的数据绑定到孩子们 使用“bindChildren”时,我可以提供可观察列表,但我必须将它们转换为节点的。这样一来,填充块就有点过时了 推荐的方法是什么?我找不到关于这个的任何东西Asynchronous 树视图的异步加载,asynchronous,kotlin,tornadofx,Asynchronous,Kotlin,Tornadofx,嘿,我对treeview异步加载数据非常陌生。我正在从rest端点加载类别,我想在那里显示 似乎没有直接的数据绑定到孩子们 使用“bindChildren”时,我可以提供可观察列表,但我必须将它们转换为节点的。这样一来,填充块就有点过时了 推荐的方法是什么?我找不到关于这个的任何东西 // Category interface Category<T : Category<T>> { val id: String val name: String val sub
// Category
interface Category<T : Category<T>> {
val id: String
val name: String
val subcategories: List<T>?
}
//default category:
class DefaultCategory(override val name: String) : Category<DefaultCategory> {
override val id: String = "default"
override val subcategories: List<DefaultCategory>? = null
}
//ViewModel
class CategoryViewModel : ViewModel() {
val sourceProperty = SimpleListProperty<Category<*>>()
fun loadData() {
// load items for treeview into 'newItems'
sourceProperty.value = newItems
}
}
// TreeViewFactoryMethod
private fun createTreeView(
listProperty: SimpleListProperty<Category<*>>
): TreeView<Category<*>> {
return treeview {
root = TreeItem(DefaultCategory("Categories"))
isShowRoot = false
root.isExpanded = true
root.children.forEach { it.isExpanded = true }
cellFormat { text = it.name }
populate { parent ->
when (parent) {
root -> listProperty.value
else -> parent.value.subcategories
}
}
}
}
//类别
接口类别{
valid:String
val名称:String
val子类别:列表?
}
//默认类别:
类DefaultCategory(覆盖值名称:字符串):类别{
覆盖val id:String=“默认”
覆盖val子类别:列表?=null
}
//视图模型
类CategoryViewModel:ViewModel(){
val sourceProperty=SimpleListProperty()
fun loadData(){
//将treeview的项目加载到“newItems”中
sourceProperty.value=newItems
}
}
//TreeviewFactory方法
私人娱乐createTreeView(
listProperty:SimpleListProperty
):TreeView{
返回树视图{
root=TreeItem(默认类别(“类别”))
isShowRoot=false
root.isExpanded=true
root.children.forEach{it.isExpanded=true}
cellFormat{text=it.name}
填充{parent->
何时(家长){
root->listProperty.value
else->parent.value.subcategories
}
}
}
}
假设在单击按钮时调用
viewmodel.loadData()
,我希望树视图在出现新数据时立即更新。(如果我能找到一种绑定方法的话)我以前从未在TornadFX中使用过bindChildren
,而您对异步的使用与我认为您的主要问题不太相关。诚然,这个问题一开始让我有些困惑,但我猜你只是想知道为什么列表没有出现在你的树视图中?我已经制作了一个测试示例,并对其进行了更改以使其正常工作
// Category
interface Category<T : Category<T>> {
val id: String
val name: String
val subcategories: List<T>?
}
//default category:
class DefaultCategory(override val name: String) : Category<DefaultCategory> {
override val id: String = "default"
override val subcategories: List<DefaultCategory>? = null
}
//Just a dummy category
class ChildCategory(override val name: String) : Category<ChildCategory> {
override val id = name
override val subcategories: List<ChildCategory>? = null
}
//ViewModel
class CategoryViewModel : ViewModel() {
//filled with dummy data
val sourceProperty = SimpleListProperty<Category<*>>(listOf(
ChildCategory("Categorya"),
ChildCategory("Categoryb"),
ChildCategory("Categoryc"),
ChildCategory("Categoryd")
).asObservable())
fun loadData() {
sourceProperty.asyncItems {
//items grabbed somehow
listOf(
ChildCategory("Category1"),
ChildCategory("Category2"),
ChildCategory("Category3"),
ChildCategory("Category4")
).asObservable()
}
}
}
class TestView : View() {
val model: CategoryViewModel by inject()
override val root = vbox(10) {
button("Refresh Items").action {
model.loadData()
}
add(createTreeView(model.sourceProperty))
}
// TreeViewFactoryMethod
private fun createTreeView(
listProperty: SimpleListProperty<Category<*>>
): TreeView<Category<*>> {
return treeview {
root = TreeItem(DefaultCategory("Categories"))
isShowRoot = false
root.isExpanded = true
root.children.forEach { it.isExpanded = true }
cellFormat { text = it.name }
populate { parent ->
when (parent) {
root -> listProperty
else -> parent.value.subcategories
}
}
}
}
}
//类别
接口类别{
valid:String
val名称:String
val子类别:列表?
}
//默认类别:
类DefaultCategory(覆盖值名称:字符串):类别{
覆盖val id:String=“默认”
覆盖val子类别:列表?=null
}
//只是一个虚拟类别
类ChildCategory(覆盖值名称:字符串):类别{
覆盖值id=name
覆盖val子类别:列表?=null
}
//视图模型
类CategoryViewModel:ViewModel(){
//填充了虚拟数据
val sourceProperty=SimpleListProperty(列表属性(
儿童类别(“类别”),
儿童类别(“类别B”),
儿童类别(“类别”),
儿童类别(“分类”)
).asObservable())
fun loadData(){
sourceProperty.asyncItems{
//不知怎么被抢走的东西
列表(
儿童类别(“类别1”),
儿童类别(“类别2”),
儿童类别(“类别3”),
儿童类别(“类别4”)
).asObservable()
}
}
}
类TestView:View(){
val模型:CategoryViewModel by inject()
覆盖val root=vbox(10){
按钮(“刷新项”)。操作{
model.loadData()
}
添加(createTreeView(model.sourceProperty))
}
//TreeviewFactory方法
私人娱乐createTreeView(
listProperty:SimpleListProperty
):TreeView{
返回树视图{
root=TreeItem(默认类别(“类别”))
isShowRoot=false
root.isExpanded=true
root.children.forEach{it.isExpanded=true}
cellFormat{text=it.name}
填充{parent->
何时(家长){
根->列表属性
else->parent.value.subcategories
}
}
}
}
}
有两个重要的区别是重要的
1。更相关的区别是,在填充块中,使用root->listProperty
而不是root.listProperty.value
。这将显示您的列表。原因是SimpleListProperty
不是列表,它包含一个列表。因此,是的,传入一个普通列表是完全有效的(就像传入list属性的值一样)。但现在这意味着树视图没有监听您的属性,只监听您传入的列表。考虑到这一点,我会考虑是否也实现了类别的子类别列表
2.其次,请注意ViewModel
中使用的asyncItems
。这将异步执行任何任务,然后将项目设置为成功时列出。您甚至可以向其添加fail
或cancel
块。我建议使用此选项,因为不应在UI线程上执行长时间/密集型操作。sourceProperty.asyncItems
是缺少的链接。非常感谢。