2017-09-05 2 views
1

Ich habe meine erste Qt-Anwendung in Entwicklung. Es ist ein Desktop-Client für Site-Messaging.QNetworkAccessManager eine Instanz und verbinden Steckplätze

Qt Dokumentation sagt, dass ich nur eine Instanz von QNetworkAccessManager über Anwendung haben muss. Aber ich lese auch, dass die Verwendung von Singletons mit Qt keine gute Idee ist. Wie kann ich eine Instanz von QNetworkAccessManager über App machen?

Eine andere Frage ist, wie man Schlitze richtig verbindet, während ich ApiHandler Funktionen von anderen Klassen nenne?

Zum Beispiel habe ich ExampleApi Klasse, die Funktionen von ApiHandler verwendet, in updateMessageList Schlitz messagesListUpdated angeschlossen werden sollte nach Wunsch im Hinblick auf aktualisieren Nachrichtenliste fertig, aber es nie genannt.

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; 
} 
+1

Ihr Manager den Bereich verlässt, bevor das Ergebnis empfangen wird. – m7913d

+1

Die Lösung kann die gleiche wie mit 'QCoreApplication' und' qApp' sein: Ja, es ist ein Singleton, aber es ist ein Singleton, dessen Lebensdauer Sie vollständig kontrollieren. –

Antwort

1

Eine Instanz von QNetworkAccessManager Snippet

QNetworkAccessManager* getManager() { 
    static QNetworkAccessManager* nam = new QNetworkAccessManager; 
    return nam; 
} 
Verwandte Themen