2017-09-05 15 views
1

開発中の最初のQtアプリケーションがあります。サイトメッセージングのデスクトップクライアントです。QNetworkAccessManager 1つのインスタンスと接続スロット

Qtのドキュメントには、QNetworkAccessManager accrossアプリケーションのインスタンスが1つだけ必要であると記載されています。しかし、Qtでのシングルトンの使用は良い考えではないことも読んでいます。どのように私はのQNetworkAccessManagerの1つのインスタンスを作ることができますか?

もう1つの質問は、私がと呼んでいる間にスロットを正しく接続する方法です。ApiHandlerは他のクラスの機能ですか?例えば

私は、要求がビュー内のメッセージのリストを更新するために、終了後を接続しなければならないが、それが呼び出されないmessagesListUpdated updateMessageListスロットに、ApiHandlerの機能を使用ExampleApiクラスを有しています。

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 QNetworkAccessManagerの

#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

あなたのマネージャーがスコープの外に出るスニペット。 – m7913d

+1

解決策は 'QCoreApplication'と' qApp'と同じです:はい、シングルトンですが、ライフタイムを完全に制御するシングルトンです。 –

答えて

1

1つのインスタンスが結果が受信される前に

QNetworkAccessManager* getManager() { 
    static QNetworkAccessManager* nam = new QNetworkAccessManager; 
    return nam; 
} 
関連する問題