(1)引子
首先,ImageProvider是为QML应用提供的、一种先进的图像加载方式。
作者建议从三点理解其定义:
- 加载方式的差异:
相比本地资源的加载方式:source : “qrc:///前缀/demo.jpg”。
ImageProvider方式: source : “image://imageproviderid/image id”。 - 先进性的体现
○ 异步加载,不会阻塞UI线程
○ 可以加载内存图像(QPixmap) - 适用性方面:
不适用于QWebEngine中的html(试过)和QWidget(还没试过)。
其原理(拍脑袋)是:先筛选source属性(url类型)的scheme(image://),
再依据imageproviderid找到所绑定的ImageProvider类实例;
在其重载的方法中,依据image id获取业务图像,返回给请求端展示。
(2)问题&对策
如何在ImageProvider中依据image id获取业务相关的图像?
或者说业务对象(Image Reader)如何与ImageProvider进行关联?
- 思路一:在ImageProvider创建的时候关联:
通常,在QML的应用Engine初始化的时候设置图像加载器:
。。。
QQmlApplicationEngine engine;
//设置图像加载器
engine.addImageProvider("imgp", new ImageProvider());
。。。
const QUrl url(QStringLiteral("qrc:/main.qml"));
。。。
而该处,qml业务对象还没有初始化(qml文件都尚未加载),
又如何能将qml业务对象实例传入到ImageProvider呢?!
所以在上述代码的基础上,有一些补充写法:
ImageReader reader;
。。。
engine.rootContext()->setContextProperty("imgReader", &reader);
engine.addImageProvider("imgp", reader->m_imageProvider);
该代码的目的就是在注册ImageProvider之前,将其和业务对象绑定。
但是新问题随之而来:业务对象又如何在qml中调用呢?
上述代码中,业务对象的调用并不是在qml中驱动的,而是子线程触发。
- 思路二:在业务对象初始化时关联
其实,单例模式和上述代码中Context Property本质相同,都是全局变量。
(3)结论
思路二无需在入口main.cpp中添加过多的代码,使用方式更灵活:既可以在qml中通过用户交互调用读取,也可以创建子线程启动后台任务。
相关文档
- QML开发避坑指南(一):图像资源的加载
- QML开发避坑指南(二):加载https图像
- QML开发避坑指南(三):webchannel中js的加载顺序