在一开始我想在网页上爬取一些内容所以我想到了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()
}