QNetworkAccessManager 一个实例和连接槽
Posted
技术标签:
【中文标题】QNetworkAccessManager 一个实例和连接槽【英文标题】:QNetworkAccessManager one instance and connecting slots 【发布时间】:2017-09-05 13:55:48 【问题描述】:我的第一个 Qt 应用程序正在开发中。它是用于站点消息传递的桌面客户端。
Qt 文档说我只需要一个 QNetworkAccessManager 跨应用程序的实例。但我也读到在 Qt 中使用单例并不是一个好主意。我如何在应用程序中创建一个 QNetworkAccessManager 实例?
另一个问题是,当我从其他类调用 ApiHandler 函数时,如何正确连接插槽?
例如,我有 ExampleApi 类,它使用 ApiHandler 的功能,在 updateMessageList 插槽中 messagesListUpdated 应该被连接请求完成后更新视图中的消息列表,但它从未调用过。
ExampleApi.h
...
#include "apihandler.h"
class ExampleApi : public QObject
Q_OBJECT
public:
explicit ExampleApi(QObject *parent = 0);
void updateMessagesList();
signals:
public slots:
void messagesListUpdated(QNetworkReply* reply);
;
ExampleApi.cpp
ExampleApi::ExampleApi(QObject *parent) :
QObject(parent)
void ExampleApi::updateMessagesList()
QMap<QString, QString> m;
m["user_id"] = ConfigParser::settings.value(USER_ID).toString();
QNetworkAccessManager nam;
ApiHandler a(&nam);
// Connect a slot
connect(a.getManager(), SIGNAL(finished(QNetworkReply*)), this, SLOT(messagesListUpdated(QNetworkReply*)));
a.makeRequest("messages.get", m);
void ExampleApi::messagesListUpdated(QNetworkReply* reply)
QJsonDocument j = QJsonDocument::fromJson(reply->readAll());
QJsonObject getjson = j.object();
qDebug() << "ExampleApi::messagesListUpdated()" << getjson;
reply->deleteLater();
// ...
ApiHandler.h
class ApiHandler : public QObject
Q_OBJECT
public:
explicit ApiHandler(QNetworkAccessManager *nam, QObject *parent = 0);
~ApiHandler();
QNetworkReply* makeRequest(QString method, QMap<QString, QString> parameters);
QNetworkAccessManager* getManager();
private:
QUrl buildCall(QString method, QMap<QString, QString> parameters);
QNetworkAccessManager* manager;
signals:
public slots:
void replyFinished(QNetworkReply* reply);
void slotReadyRead();
void slotError(QNetworkReply::NetworkError error);
void slotSslErrors(QList<QSslError> errorList);
;
ApiHandler.cpp
#include "apihandler.h"
ApiHandler::ApiHandler(QNetworkAccessManager *nam, QObject *parent) :
QObject(parent), manager(nam)
Q_ASSERT(manager);
ApiHandler::~ApiHandler()
manager->deleteLater();
QUrl ApiHandler::buildCall(QString method, QMap<QString, QString> parameters)
QUrl url = QUrl(API_URL + method);
QUrlQuery query;
ConfigParser c;
// Append first access_token
query.addQueryItem("access_token", c.settings.value(ACCESS_TOKEN_KEY).toString());
if (!parameters.isEmpty())
QMapIterator<QString, QString> i(parameters);
while (i.hasNext())
i.next();
query.addQueryItem(i.key(), i.value());
url.setQuery(query.query());
return url;
QNetworkReply* ApiHandler::makeRequest(QString method, QMap<QString, QString> parameters)
QUrl url = this->buildCall(method, parameters);
//qDebug() << "ApiHandler::makeRequest: " << url;
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("User-Agent", "Site-Client");
QNetworkReply *reply = manager->get(request);
connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(slotSslErrors(QList<QSslError>)));
return reply;
void ApiHandler::replyFinished(QNetworkReply* reply)
qDebug() << "ApiHandler::replyFinished:" << reply->url();
QJsonDocument j = QJsonDocument::fromJson(reply->readAll());
if (j.isEmpty())
// throw error
qDebug("ApiHandler::replyFinished(...) j.isEmpty :(");
else
qDebug() << "ApiHandler::replyFinished(...)" << j;
reply->deleteLater();
void ApiHandler::slotReadyRead()
//qDebug("slotReadyRead");
void ApiHandler::slotError(QNetworkReply::NetworkError error)
qWarning() << "raised error:" << error;
void ApiHandler::slotSslErrors(QList<QSslError> errorList)
qWarning() << "raised sslErrors" << errorList;
QNetworkAccessManager* ApiHandler::getManager()
return this->manager;
【问题讨论】:
您的经理在收到结果之前就超出了范围。 解决方案可以与QCoreApplication
和qApp
相同:是的,它是一个单例,但它是一个您完全控制其生命周期的单例。
【参考方案1】:
QNetworkAccessManager sn-p的一个实例
QNetworkAccessManager* getManager()
static QNetworkAccessManager* nam = new QNetworkAccessManager;
return nam;
【讨论】:
以上是关于QNetworkAccessManager 一个实例和连接槽的主要内容,如果未能解决你的问题,请参考以下文章
QNetworkAccessManager 一个实例和连接槽
QNetworkAccessManager 可以从不同的线程获取/发布吗?
错误:没有用于调用“QNetworkAccessManager::QNetworkAccessManager(Networking* const)”的匹配函数