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

来源:互联网 发布:韩国剑灵捏脸数据 编辑:程序博客网 时间:2024/06/05 09:25

正在做一个第三方微信企业要接口的项目,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()<<accessToken;    }    reply->deleteLater();    qDebug()<<"finished";}
通过比较之前的代码片,我想应该很好看出不同,不仅within一个方法,而且代码也更好读更短,QNetworkAccessManager的操作封装在一个函数中了。


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



0 0
原创粉丝点击