如何拥有QNetworkAccessManager的一个实例?

时间:2018-06-05 02:23:07

标签: c++ qt oop c++11 design-patterns

有一个类似的question,但我发现它对我的问题没有用。

在Qt documentation中,他们说:

  

对于整个Qt应用程序,一个QNetworkAccessManager实例应该足够了。

在我的应用程序中,我在几个地方使用QNetworkAccessManager(它们可能同时被调用),每次我在堆栈上创建新实例时。在阅读该引用之后,我将我的代码更改为静态QNetworkAccessManager并在任何地方使用它。在将其更改为静态成员后,我总是收到警告:

QObject::connect: Cannot connect (null)::aboutToQuit() to QNativeWifiEngine::closeHandle()

在这两种情况下,代码都可以正常运行,但是,文档让我感到困惑。由于该产品将是商业化的,我认为这个问题很严重。我应该遵循文档还是避免警告?或者您是否建议其他方式?

如果另一个线程上的对象需要使用QNetworkAccessManager

,该怎么办?

<小时/> 编辑:添加代码

单身人士设置类:

class ConnectionSettingsSingleton
{
   ...
   // constructors = default
   // copy constructor = delete

   public:
      static QNetworkAccessManager networkAccessManager;
}

我在不同的地方使用networkAccessManager,但方式相同:

QNetworkReply* HttpClient::makeRequest()
{
   switch (this->method) {
   case RequestMethod::GET:
      return ConnectionSettingsSingleton::networkAccessManager.get(this->serverRequest);
   case RequestMethod::POST:
      return ConnectionSettingsSingleton::networkAccessManager.post(this->serverRequest, QJsonDocument(this->data).toJson());
   case RequestMethod::DELETE:
      return ConnectionSettingsSingleton::networkAccessManager.deleteResource(this->serverRequest);
   default:
      return nullptr;
   }
}

<小时/> EDIT-2

我很善意地使用Kuba Ober's answer,但有一次我得到了这个警告:

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNetworkAccessManager(0x26f6d0), parent's thread is QThread(0x2b73b8), current thread is QThread(0xa4f20a8)

原因:我尝试从其他线程访问QNAM。因此,我更新了我的问题。

1 个答案:

答案 0 :(得分:2)

您可以随意使用整个Qt。不要使用静态变量 - 你不能控制它们的生命周期,而且这种生命周期几乎总是错误的。 QNetworkManager不存在时,QCoreApplication不应存在。警告根本不是良性的 - 它表明了一个基本的设计问题。 需要控制经理的生命周期,并确保其不会超过QApplication。管理此类全局应用程序绑定对象的规范方法是将它们保存为main中的自动变量,并使用辅助函数来访问它们。 QPointer会自动跟踪对象的生命周期,从而不会晃来晃去。因此:

main.h - interface

QNetworkAccessManager *nMgr();

main.cpp - 实现

// This pointer is local to the translation unit, and is an
// implementation detail. It's not used anywhere else.
static QPointer<QNetworkAccessManager> globalManager;

// The global accessor method
QNetworkAccessManager *nMgr() {
  Q_ASSERT(!qApp || QThread::currentThread() == qApp->thread());
  return globalManager;
}

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);
  QNetworkAccessManager mgr;
  globalManager = &mgr;
  ...
}