在一开始我想在网页上爬取一些内容所以我想到了C++中的 QNetworkAccessManager 类 然后很自然的写了
QNetworkRequest request; request.setUrl(QUrl(m_url) ); QNetworkReply * qreply= manager->get(request );但是这并不可以控制超时时间,我一直以为QNetworkAccessManager这么大一个类一定有设置超时时间的地方,然后也去网上查找发现并没有. 于是发现别人的一个方法 QReplyTimeout :
#ifndef REPLYTIMEOUT_H #define REPLYTIMEOUT_H /** QReplyTimeout 控制超时时间 **/ #include <QObject> #include <QTimer> #include <QNetworkReply> class QReplyTimeout : public QObject { Q_OBJECT public: QReplyTimeout(QNetworkReply *reply, const int timeout) : QObject(reply) { Q_ASSERT(reply); if (reply && reply->isRunning()) { // 启动单次定时器 QTimer::singleShot(timeout, this, SLOT(onTimeout())); } } signals: void timeout(); // 超时信号 - 供进一步处理 private slots: void onTimeout() { // 处理超时 QNetworkReply *reply = static_cast<QNetworkReply*>(parent()); if (reply->isRunning()) { emit timeout(); reply->abort(); reply->deleteLater(); } } }; #endif // REPLYTIMEOUT_H这个类一看内容就大概知道怎么使用了 于是我将代码改成如下:
QNetworkAccessManager * manager = new QNetworkAccessManager(); QNetworkRequest request; request.setUrl(QUrl(m_url) ); QNetworkReply * qreply= manager->get(request ); QReplyTimeout *pTimeout = new QReplyTimeout(qreply, m_outTime); //下载超时 connect(pTimeout, &QReplyTimeout::timeout, [=]() { qDebug() << "Timeout"; emit responseFaild(); }); connect(manager,&QNetworkAccessManager::finished,[=](){ QString str = qreply->readAll(); XXX qreply->abort(); qreply->deleteLater(); emit responseSuccessful(Space2nbsp(rx.capturedTexts()[1])); } });这样在电脑上测试没有任何问题,但是在手机android上,如果触碰任何的东西都会导致闪退我猜测是没有多线程的原因. 于是我将 这一整段代码 全都移到了 run中 然后 start 发现并不能 读取内容,因为如果没有让线程消息循环的话,没有时间读取网页,所以在末尾加上 this->exec();
void request::run() { QNetworkAccessManager * manager = new QNetworkAccessManager(); QNetworkRequest request; request.setUrl(QUrl(m_url) ); QNetworkReply * qreply= manager->get(request ); QReplyTimeout *pTimeout = new QReplyTimeout(qreply, m_outTime); //下载超时 connect(pTimeout, &QReplyTimeout::timeout, [=]() { qDebug() << "Timeout"; emit responseFaild(); this->quit(); }); //多线程下载数据 成功 connect(manager,&QNetworkAccessManager::finished,[=](){ QString str = qreply->readAll(); XXX emit responseSuccessful(Space2nbsp(rx.capturedTexts()[1])); this->quit(); } }); this->exec(); }在main中 首先要让C++文件可以 被QML发现
#include "Request.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); qmlRegisterType<Request>("REQUEST", 1, 0, "Request");// QML导入的时候就是import REQUEST 1.0 }在QML 中 创建 这个C++对象
Request{ id: r_netrequest onResponseSuccessful:{ 成功 } onResponseFaild:{ 超时失败等 } } 启动线程 : r_netrequest.start() 关闭线程 : r_netrequest.quit() 我习惯性的加上了 //删除界面时 关闭线程 Component.onDestruction: { r_netrequest.quit() r_netrequest.wait() }