QNetworkAccessManager不使用信号/槽机制来获得QNetworkReply的解决办法

正在做一个第三方微信企业要接口的项目,JAVA的实现方法比较简单,网上资料也很多。

但是我需要在C++下实现,微信企业号接口大多都是https的GET/POST方法实现的。

Qt提供了一个封装好的类QNetworkAccessManager,就不需要使用windows的套接字来编程了,也脱离的平台限制。

上图是我从http://blog.csdn.net/chenlong12580/article/details/7392766 当中借来得,这位兄弟也很好的演示了QNetworkAccessManager的基本调用方法。

但是QNetworkAccessManager是为图形界面而设计的,当Manager得到finished()信号时,使用一个SLOT函数去做读取数据的事,这对于显示在GUI的数据时,可以说不能再好用了。


但是微信企业号在调用任何的接口之前,都需要获得一个认证,就是access_token,需要使用GET方式来获得,这使得我需要将获得access_token的方法封装成一个函数,以便在每次具体的如发送微信之前,调用它。

贴上代码:

void MainWindow::getAccessToken()
{
    QNetworkAccessManager *manager = new QNetworkAccessManager(this);
    connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(finishedSlot(QNetworkReply*)),Qt::DirectConnection);
    QNetworkReply* reply = manager->get(QNetworkRequest(QUrl(ACCESS_TOKEN_URL)));
}

void MainWindow::finishedSlot(QNetworkReply* reply)
{
    qDebug()<<"start";
    QVariant statusCodeV =
         reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    QVariant redirectionTargetUrl =
         reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
    if(reply->error()==QNetworkReply::NoError)
    {
        QByteArray bytes = reply->readAll();
        QString rlt =QString::fromUtf8(bytes);
        accessToken = rlt;
    }
    reply->deleteLater();
    //ACCESS_FLAG = true;
    qDebug()<<"finished";
}

以上就是按照官方文档来实现的代码片。

如果我再main中直接调用

getAccessToken()
的话,程序会直接运行之后的代码片,而不会先运行SLOT,因为他们在同一线程。

而如果用C++11的 thread.h 用多线程调用,编译器也不认QNetworkReply为valid的type,并且多线程也不符合代码的逻辑,因为主线程要等待子线程,且只有一个子线程。

解决的办法就是使用QEventLoop:直接上代码:

void MainWindow::getAccessToken()
{
    QEventLoop temp_loop;
    QNetworkAccessManager *manager = new QNetworkAccessManager(this);
    QNetworkReply* reply = manager->get(QNetworkRequest(QUrl(ACCESS_TOKEN_URL)));
    connect(reply, SIGNAL(finished()), &temp_loop, SLOT(quit()));
    temp_loop.exec();
    qDebug()<<"start";
    QVariant statusCodeV =
         reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    QVariant redirectionTargetUrl =
         reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
    if(reply->error()==QNetworkReply::NoError)
    {
        QByteArray bytes = reply->readAll();
        QString rlt =QString::fromUtf8(bytes);
        accessToken = rlt;
        qDebug()<deleteLater();
    qDebug()<<"finished";
}
通过比较之前的代码片,我想应该很好看出不同,不仅within一个方法,而且代码也更好读更短,QNetworkAccessManager的操作封装在一个函数中了。


这里还要提一点,按照文档的资料,QNetworkReply的waitForReadyRead()函数,应该也可以完成上述操作,但是我发现不管设置几秒的等待,函数都无脑回false,看网上说Qt在某个版本后这个函数失效了,我用的是Qt5.4,可能4.x下可以用,应该也是可以实现的的。



你可能感兴趣的:(微信企业,Qt,HTTP,C++)