Skip to content

Commit f78019b

Browse files
committed
异步加载qml
1 parent d61fcee commit f78019b

8 files changed

Lines changed: 197 additions & 24 deletions

File tree

src/dde-control-center/dccmanager.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ DccManager::DccManager(QObject *parent)
7676
QJSEngine::setObjectOwnership(m_noParentObjects, QQmlEngine::CppOwnership);
7777

7878
initConfig();
79-
connect(m_plugins, &PluginManager::addObject, this, &DccManager::addObject, Qt::QueuedConnection);
79+
connect(m_plugins, &PluginManager::addObject, this, &DccManager::addObject);
8080
connect(m_plugins, &PluginManager::loadAllFinished, this, &DccManager::tryShow, Qt::QueuedConnection);
8181
m_showTimer = new QTimer(this);
8282
connect(m_showTimer, &QTimer::timeout, this, &DccManager::tryShow);
@@ -191,10 +191,12 @@ void DccManager::addObject(DccObject *obj)
191191
{
192192
if (!obj)
193193
return;
194+
qWarning()<<__LINE__<<__FUNCTION__<<obj;
194195
QVector<DccObject *> objs;
195196
objs.append(obj);
196197
while (!objs.isEmpty()) {
197198
DccObject *o = objs.takeFirst();
199+
qWarning()<<__LINE__<<__FUNCTION__<<(void*)o;
198200
if (!o->name().isEmpty()) {
199201
m_objMap[o->name()].append(o);
200202
connect(o, &DccObject::destroyed, this, &DccManager::onDccObjectDestroyed, Qt::UniqueConnection);
@@ -782,7 +784,7 @@ void DccManager::clearShowParam()
782784

783785
void DccManager::tryShow()
784786
{
785-
if (m_showUrl.isEmpty() && !m_activeObject) {
787+
if (m_showUrl.isEmpty() && m_showTimer) {
786788
clearShowParam();
787789
showPage(m_root, QString());
788790
return;
@@ -806,6 +808,9 @@ void DccManager::tryShow()
806808
QDBusConnection::sessionBus().send(m_showMessage.createErrorReply(QDBusError::InvalidArgs, QString("not found url:") + m_showUrl));
807809
}
808810
clearShowParam();
811+
if (!m_activeObject) {
812+
showPage(m_root, QString());
813+
}
809814
}
810815
}
811816

src/dde-control-center/plugin/dccobject.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include <QQuickItem>
1212
#include <QQuickWindow>
1313
#include <QTimer>
14-
14+
#include <QThread>
1515
namespace dccV25 {
1616
static Q_LOGGING_CATEGORY(dccLog, "dde.dcc.object");
1717

@@ -30,11 +30,16 @@ DccObject::Private::Private(DccObject *obj)
3030
, m_currentObject(nullptr)
3131
, m_page(nullptr)
3232
, m_parentItem(nullptr)
33+
, m_pParent(nullptr)
3334
{
3435
}
3536

3637
DccObject::Private::~Private()
3738
{
39+
if(m_pParent){
40+
m_pParent->removeObject(q_ptr);
41+
}
42+
clearObject();
3843
if (m_page && (!m_page->parent() || m_page->parent() == q_ptr)) {
3944
// Use deleteLater() to avoid dangling QObjectWrapper references in QML's
4045
// JS engine. Synchronous delete can cause crashes when GC runs during
@@ -46,6 +51,7 @@ DccObject::Private::~Private()
4651
}
4752
if (m_parent) {
4853
m_parent->p_ptr->removeChild(q_ptr);
54+
// m_parent->removeObject(q_ptr);
4955
}
5056
while (!m_children.isEmpty()) {
5157
DccObject *child = m_children.first();
@@ -55,6 +61,10 @@ DccObject::Private::~Private()
5561
// delete, then defer destruction so QML's GC can safely process any
5662
// remaining QObjectWrapper references to this child.
5763
child->setParent(nullptr);
64+
// if(child->p_ptr->m_pParent){
65+
// child->p_ptr->m_pParent->removeObject(child);
66+
// // child->p_ptr->m_pParent = nullptr;
67+
// }
5868
child->deleteLater();
5969
}
6070
}
@@ -193,20 +203,24 @@ void DccObject::Private::addObject(DccObject *child)
193203
{
194204
if (child && !m_objects.contains(child)) {
195205
m_objects.append(child);
206+
child->p_ptr->m_pParent=this;
196207
Q_EMIT q_ptr->addObject(child);
197208
}
198209
}
199210

200211
void DccObject::Private::removeObject(DccObject *child)
201212
{
202-
if (child && m_objects.removeOne(child)) {
213+
if (child ) {
214+
child->p_ptr->m_pParent=nullptr;
215+
m_objects.removeOne(child);
203216
Q_EMIT q_ptr->removeObject(child);
204217
}
205218
}
206219

207220
void DccObject::Private::clearObject()
208221
{
209222
for (auto obj : m_objects) {
223+
obj->p_ptr->m_pParent=nullptr;
210224
Q_EMIT q_ptr->removeObject(obj);
211225
}
212226
m_objects.clear();
@@ -249,10 +263,12 @@ DccObject::DccObject(QObject *parent)
249263
: QObject(parent)
250264
, p_ptr(new DccObject::Private(this))
251265
{
266+
qWarning()<<__LINE__<<__FUNCTION__<<"===== ===="<<this<<QThread::currentThread();
252267
}
253268

254269
DccObject::~DccObject()
255270
{
271+
qWarning()<<__LINE__<<__FUNCTION__<<"===== ~~~ ===="<<this<<name()<<QThread::currentThread();
256272
delete p_ptr;
257273
}
258274

src/dde-control-center/plugin/dccobject_p.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class DccObject::Private
7979
QObjectList m_data; // data属性,为qml能加子项
8080
QPointer<QQmlComponent> m_page;
8181
QPointer<QQuickItem> m_parentItem; // Item父项
82+
DccObject::Private *m_pParent;
8283

8384
QString m_parentName;
8485
QString m_displayName;

src/dde-control-center/plugin/dccrepeater.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class DccRepeaterPrivate
3434

3535
for (int i = 0; i < itemCount; i++) {
3636
if (i >= deletables.size() || !deletables.at(i))
37-
model->object(i, QQmlIncubator::AsynchronousIfNested);
37+
model->object(i, QQmlIncubator::Asynchronous);
3838
}
3939
}
4040

@@ -185,6 +185,8 @@ void DccRepeater::createdItem(int index, QObject *item)
185185
{
186186
DccObject *dccObj = qmlobject_cast<DccObject *>(item);
187187
if (dccObj) {
188+
Q_D(const DccRepeater);
189+
d->model->object(index);
188190
dccObj->setParent(this);
189191
p_ptr->addObject(dccObj);
190192
Q_EMIT objAdded(index, item);

src/dde-control-center/pluginmanager.cpp

Lines changed: 162 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <QQmlComponent>
2020
#include <QQmlContext>
2121
#include <QQmlFile>
22+
#include <QQmlIncubator>
2223
#include <QRunnable>
2324
#include <QSet>
2425
#include <QSettings>
@@ -114,6 +115,7 @@ class LoadPluginTask : public QRunnable
114115
protected:
115116
void run() override;
116117
void doLoadSo();
118+
void doCreate();
117119

118120
protected:
119121
PluginManager *m_pManager;
@@ -123,10 +125,34 @@ class LoadPluginTask : public QRunnable
123125
void LoadPluginTask::run()
124126
{
125127
m_data->thread = QThread::currentThread();
126-
doLoadSo();
128+
doCreate();
127129
m_data->thread = nullptr;
128130
}
129131

132+
void LoadPluginTask::doCreate()
133+
{
134+
QElapsedTimer timer;
135+
timer.start();
136+
Q_EMIT m_pManager->updatePluginStatus(m_data, DataBegin, "load plugin begin");
137+
QObject *dataObj = nullptr;
138+
if (m_data->factory) {
139+
dataObj = m_data->factory->create();
140+
if (dataObj && dataObj->parent()) {
141+
dataObj->setParent(nullptr);
142+
}
143+
}
144+
if (dataObj) {
145+
m_data->data = dataObj;
146+
}
147+
if (m_data->data) {
148+
m_data->data->moveToThread(m_pManager->thread());
149+
}
150+
if (m_data->factory) {
151+
m_data->factory->moveToThread(m_pManager->thread());
152+
}
153+
Q_EMIT m_pManager->updatePluginStatus(m_data, DataEnd, ": create date finished. elapsed time :" + QString::number(timer.elapsed()));
154+
}
155+
130156
void LoadPluginTask::doLoadSo()
131157
{
132158
Q_EMIT m_pManager->updatePluginStatus(m_data, DataBegin, "load plugin begin");
@@ -188,6 +214,73 @@ void LoadPluginTask::doLoadSo()
188214
Q_EMIT m_pManager->updatePluginStatus(m_data, DataEnd, ": load plugin finished. elapsed time :" + QString::number(timer.elapsed()));
189215
}
190216

217+
218+
class DccIncubator : public QQmlIncubator
219+
{
220+
public:
221+
DccIncubator(PluginManager *pManager,PluginData *data,QQmlComponent *component,QQmlContext *context)
222+
: QQmlIncubator(Asynchronous)
223+
, m_pManager(pManager)
224+
, m_data(data)
225+
, m_component(component)
226+
,m_context(context)
227+
{
228+
}
229+
230+
protected:
231+
// 当对象孵化(创建)完成时调用
232+
void setInitialState(QObject *object) override
233+
{
234+
// 这里可以做一些初始化设置,但通常建议在 statusChanged 中处理
235+
QQmlIncubator::setInitialState(object);
236+
}
237+
238+
void statusChanged(Status status) override
239+
{
240+
switch(status){
241+
case Ready:{
242+
QObject *obj = object();
243+
m_component->deleteLater();
244+
if (!obj) {
245+
m_context->deleteLater();
246+
Q_EMIT m_pManager->updatePluginStatus(m_data, MainObjErr | MainObjEnd, " component create main object is null:" + m_component->errorString());
247+
return;
248+
}
249+
m_context->setParent(m_context);
250+
obj->setParent(m_data->module ? m_data->module : nullptr);
251+
m_data->mainObj = qobject_cast<DccObject *>(obj);
252+
qWarning()<<__LINE__<<__FUNCTION__<<"=====MainEnd===="<<obj<<m_data->mainObj<<m_data->name<<QThread::currentThread();
253+
Q_EMIT m_pManager->updatePluginStatus(m_data, MainObjEnd, ": create main finished");
254+
// Q_EMIT objectFinished(object());
255+
}break;
256+
case Error:{
257+
Q_EMIT m_pManager->updatePluginStatus(m_data, MainObjErr | MainObjEnd, " component create main object error:" + m_component->errorString());
258+
m_component->deleteLater();
259+
// Q_EMIT objectFinished(nullptr);
260+
}break;
261+
default:
262+
break;
263+
}
264+
265+
// if (status == Ready) {
266+
// // 对象创建成功,object() 返回的是 QObject*,需要转换为具体类型
267+
// QObject *obj = object();
268+
// qDebug() << "对象异步创建成功:" << obj;
269+
// // 发射信号通知外部
270+
// Q_EMIT objectFinished(obj);
271+
// } else if (status == Error) {
272+
// qWarning() << "异步创建出错:" << errors();
273+
// Q_EMIT objectFinished(nullptr);
274+
// }
275+
}
276+
private:
277+
PluginManager *m_pManager;
278+
PluginData *m_data;
279+
QQmlComponent *m_component;
280+
QQmlContext *m_context;
281+
282+
};
283+
191284
PluginManager::PluginManager(DccManager *parent)
192285
: QObject(parent)
193286
, m_manager(parent)
@@ -336,15 +429,68 @@ void PluginManager::loadPlugin(PluginData *plugin)
336429
}
337430
loadMain(plugin);
338431
} else if ((plugin->status & (ModuleEnd | DataBegin)) == ModuleEnd) {
432+
auto loadfun = [&]() {
433+
const QString soPath = plugin->path + "/" + plugin->name + ".so";
434+
QElapsedTimer timer;
435+
timer.start();
436+
if (QFile::exists(soPath)) {
437+
if (isDeleting()) {
438+
return;
439+
}
440+
QPluginLoader loader(soPath);
441+
Q_EMIT updatePluginStatus(plugin, DataLoad, QString());
442+
loader.load();
443+
if (isDeleting()) {
444+
return;
445+
}
446+
if (!loader.isLoaded()) {
447+
Q_EMIT updatePluginStatus(plugin, DataErr, "Load the plugin failed." + loader.errorString());
448+
} else {
449+
const auto &meta = loader.metaData();
450+
do {
451+
const auto iid = meta["IID"].toString();
452+
if (iid.isEmpty() || iid != QString(qobject_interface_iid<DccFactory *>())) {
453+
Q_EMIT updatePluginStatus(plugin, DataErr, "Error iid:" + iid);
454+
break;
455+
}
456+
457+
if (!loader.instance()) {
458+
Q_EMIT updatePluginStatus(plugin, DataErr, "instance() failed." + loader.errorString());
459+
break;
460+
}
461+
DccFactory *factory = qobject_cast<DccFactory *>(loader.instance());
462+
if (!factory) {
463+
Q_EMIT updatePluginStatus(plugin, DataErr, "The plugin isn't a DccFactory." + soPath);
464+
loader.unload();
465+
break;
466+
}
467+
QObject *dataObj = factory->dccObject();
468+
// if (dataObj && dataObj->parent()) {
469+
// dataObj->setParent(nullptr);
470+
// }
471+
// if (dataObj) {
472+
// plugin->data = dataObj;
473+
// }
474+
// if (plugin->data) {
475+
// plugin->data->moveToThread(thread());
476+
// }
477+
plugin->factory = factory;
478+
} while (false);
479+
}
480+
}
481+
qWarning() << __LINE__ << __FUNCTION__ <<plugin->name<< ": load plugin finished. elapsed time :" << QString::number(timer.elapsed());
482+
};
339483
if (plugin->module) {
340484
disconnect(plugin->module, nullptr, this, nullptr);
341485
if (plugin->module->isVisibleToApp()) {
486+
loadfun();
342487
threadPool()->start(new LoadPluginTask(plugin, this));
343488
} else {
344489
connect(plugin->module, &DccObject::visibleToAppChanged, this, &PluginManager::onVisibleToAppChanged);
345490
Q_EMIT updatePluginStatus(plugin, PluginEnd, QString());
346491
}
347492
} else {
493+
loadfun();
348494
threadPool()->start(new LoadPluginTask(plugin, this));
349495
}
350496
} else if ((plugin->status & (MetaDataEnd | ModuleLoad)) == MetaDataEnd) {
@@ -502,17 +648,20 @@ void PluginManager::createMain(QQmlComponent *component)
502648
case QQmlComponent::Ready: {
503649
QQmlContext *context = new QQmlContext(component->engine());
504650
context->setContextProperties({ { "dccData", QVariant::fromValue(plugin->data) }, { "dccModule", QVariant::fromValue(plugin->module) } });
505-
QObject *object = component->create(context);
506-
component->deleteLater();
507-
if (!object) {
508-
context->deleteLater();
509-
Q_EMIT updatePluginStatus(plugin, MainObjErr | MainObjEnd, " component create main object is null:" + component->errorString());
510-
return;
511-
}
512-
context->setParent(object);
513-
object->setParent(plugin->module ? plugin->module : m_rootModule);
514-
plugin->mainObj = qobject_cast<DccObject *>(object);
515-
Q_EMIT updatePluginStatus(plugin, MainObjEnd, ": create main finished");
651+
DccIncubator *incubator = new DccIncubator(this,plugin,component,context);
652+
653+
component->create(*incubator,context,nullptr);
654+
// QObject *object = component->create(context);
655+
// component->deleteLater();
656+
// if (!object) {
657+
// context->deleteLater();
658+
// Q_EMIT updatePluginStatus(plugin, MainObjErr | MainObjEnd, " component create main object is null:" + component->errorString());
659+
// return;
660+
// }
661+
// context->setParent(object);
662+
// object->setParent(plugin->module ? plugin->module : m_rootModule);
663+
// plugin->mainObj = qobject_cast<DccObject *>(object);
664+
// Q_EMIT updatePluginStatus(plugin, MainObjEnd, ": create main finished");
516665
} break;
517666
case QQmlComponent::Error: {
518667
Q_EMIT updatePluginStatus(plugin, MainObjErr | MainObjEnd, " component create main object error:" + component->errorString());
@@ -554,13 +703,13 @@ void PluginManager::addMainObject(PluginData *plugin)
554703
} else {
555704
Q_EMIT updatePluginStatus(plugin, MainObjErr, "The plugin isn't main DccObject");
556705
}
557-
Q_EMIT updatePluginStatus(plugin, MainObjEnd | PluginEnd, "add main object finished");
558706
if (plugin->mainObj) {
559707
Q_EMIT addObject(plugin->mainObj);
560708
}
561709
if (plugin->soObj) {
562710
Q_EMIT addObject(plugin->soObj);
563711
}
712+
Q_EMIT updatePluginStatus(plugin, MainObjEnd | PluginEnd, "add main object finished");
564713
}
565714

566715
void PluginManager::moduleLoading()

0 commit comments

Comments
 (0)