让GtkListStore支持数据延迟加载的构想

GtkListStore支持数据延迟加载的构想

 

转载时请注明出处:http://blog.csdn.net/absurd/

 

最近遇到一个问题,在名片列表中要显示全部名片,我们最大名片条数限制是5000条,一下子全部检索过来会非常慢。为了解决这类问题,我们在数据库封装层做了优化,即使全部检索了,但它只从数据库中取前30条,其余数据直到应用程序使用时才从数据库中获取,这种延迟加载的方式会有更好的性能表现。

 

现在才发现数据库封装层做了优化还不够,原因是GtkTreeView(也可以用来实现ListBox)不支持像Win32下的ListBox所具有Ownerdraw(自绘)功能,它需要在开始时就加载所有数据,结果仍然无法实现延迟加载,数据库封装层做的优化失去了效果。

 

为了解决这个问题,需要对GtkListStore改造。分析相关源代码后,我们发现:

1.         GtkTreeView/GtkTreeModel采用了MVC模型。GtkTreeViewview,负责显示控制,而GtkTreeModelmodel,负责数据管理。

2.         GtkTreeModel只是个接口,它有两种实现,GtkListStoreGtkTreeStore,它们分别实现了ListTree的数据管理。

3.         为了支持不同的数据表现形式,GtkTreeView并不负责每个具体项(Item)的绘制,具体项的绘制由GtkCellRenderer完成。GtkCellRenderer有几种不同的实现方式:GtkCellRendererTextGtkCellRendererPixbufGtkCellRendererToggleGtkCellRendererComboGtkCellRendererProgress

4.         在控件显示时,GtkTreeView负责从GtkTreeModel中获得数据,然后把数据传递给GtkCellRenderer,并调用GtkCellRenderer的函数去绘制。

 

很容易想到:在创建时,向GtkTreeModel加入假数据(如记录序号),直到GtkTreeViewGtkTreeModel索取数据时,才从数据库获取。但遇到两个问题:

1.         GtkTreeView和所有GtkWidget一样,先要在size_request里计算控件的大小,这里它要把每一项的get_value调用一遍,也就是说在显示之前仍然要把所有数据取出来。

2.         重载GtkTreeModelget_value函数比较困难。麻烦在于GtkTreeModelIface是个接口,GtkListStore实现了它,它不像普通虚函数可以重载。对于glib接口,你只能去实现这个接口,而不能重载接口的一个函数。

 

对于第一个问题,我们做了些简化处理,因为我们列表中的所有项的高度及宽度一样,在size_request阶段调用get_value时,可以返回一个默认值,说以便GtkTreeView可以计算控件大小。

 

对于第二个问题,我们决定对GtkListStore扩展,而不是重载。让应用程序可以hookGtkListStoreget_value函数的调用。这很简单,设置一个回调函数就行了。

 

做了简单测试,证明此方案可行,但还需要进一步验证。此方案虽然可行,但不够优雅,不知道大家有什么好办法没有。

 

~~end~~

 

 

 
原文地址:https://www.cnblogs.com/zhangyunlin/p/6167813.html