J'ai ma première application Qt en développement. C'est un client de bureau pour la messagerie de site.QNetworkAccessManager une instance et des slots de connexion
La documentation de Qt indique que je n'ai besoin que d'une seule instance de QNetworkAccessManager en regard de l'application. Mais j'ai aussi lu que l'utilisation de singletons avec Qt n'est pas une bonne idée. Comment puis-je faire une instance de QNetworkAccessManager à travers l'application?
Une autre question est de savoir comment connecter correctement les slots alors que j'appelle ApiHandler fonctions d'autres classes?
Par exemple, j'ai ExampleApi classe qui utilise les fonctions de ApiHandler, dans updateMessageList fente messagesListUpdated doit être connecté après demande terminé la mise à jour la liste des messages en vue, mais il n'a jamais appelé.
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;
}
Votre gestionnaire est hors de portée avant que le résultat est reçu. – m7913d
La solution peut être la même qu'avec 'QCoreApplication' et' qApp': oui, c'est un singleton, mais c'est un singleton dont vous contrôlez entièrement la durée de vie. –