在不断使用该库的过程中会遇到这样的一个问题,比如错误提示我只需要打印到终端就可以了,每一次的请求都需要定义一个槽函数然后等待异步调用.在这个过程中,需要定义一个槽函数就会略显得有些繁琐了.
Lambda表达式的支持就是为了解决这类问题,但是事物都有两面性,lambda的支持在使用的方便同时也会增加使用的复杂性.有关与lambda的介绍,可以查看历史文章"这是一个函数[](){}"了解.
1. 使用Lambda的简化对比
m_service.get("https://www.qt.io")
.onResopnse([](QByteArray result){ qDebug()<<"Result: "<<result; })
.onResopnse([](qint64 recv, qint64 total){ qDebug()<<"Total: "<<total<<"; Received: "<<recv; })
.onError([](QString errorStr){ qDebug()<<"Error: "<<errorStr; })
.exec();
m_service.get("https://www.qt.io")
.onResponse(this, SLOT(finish(QByteArray)))
.onResponse(this, SLOT(downloadProgress(qint64,qint64)))
.onError(this, SLOT(error(QString)))
.exec();
对比lambda表达式的网络请求
(1) 两条请求的作用是一样的,写法不一样。第一个请求的写法是lambda表达式的写法,而第二个请求的写法则是通过绑定信号与槽的写法,但它需要创建槽函数,使用起来会繁琐一点;
(2) 使用lambda方式会大大简化代码,避免繁琐操作.
2. 接口的变化
(1) 在HttpRequest类对外新增以下接口:
HttpRequest &onResopnse(std::function<void (QNetworkReply*)> lambda);
HttpRequest &onResopnse(std::function<void (QVariantMap)> lambda);
HttpRequest &onResopnse(std::function<void (QByteArray)> lambda);
HttpRequest &onResopnse(std::function<void (qint64, qint64)> lambda);
HttpRequest &onError(std::function<void (QNetworkReply::NetworkError)> lambda);
HttpRequest &onError(std::function<void (QString)> lambda);
HttpRequest &onError(std::function<void (QNetworkReply::NetworkError, QNetworkReply*)> lambda);
HttpRequest &onError(std::function<void (QString, QNetworkReply*)> lambda);
(2) 使用std::function的形式来支持对应的执行操作;
3. Lambda注册
(1) 通过提前注册类型到元对象系统,利用元对象系统的QVariant将std::function模板保存起来;
Q_DECLARE_METATYPE(std::function<void (QNetworkReply*)>);
Q_DECLARE_METATYPE(std::function<void (QByteArray)>);
Q_DECLARE_METATYPE(std::function<void (QVariantMap)>);
Q_DECLARE_METATYPE(std::function<void (QString)>);
Q_DECLARE_METATYPE(std::function<void (QNetworkReply::NetworkError)>);
Q_DECLARE_METATYPE(std::function<void (QNetworkReply::NetworkError, QNetworkReply *)>);
Q_DECLARE_METATYPE(std::function<void (QString, QNetworkReply *)>);
Q_DECLARE_METATYPE(std::function<void (qint64, qint64)>);
(2) 通过增加methodParams的"lambda"字段属性,用来判断其执行的方法.
static const QMap<QString, QMap<QString, QVariant>> methodParams =
{
{
N2S(HttpResponse::onResponse_QNetworkReply_A_Pointer),
{
{"types", QStringList({T2S(QNetworkReply*)})},
{"lambda", T2S(std::function<void (QNetworkReply*)>)},
{"signal", SIGNAL(finished(QNetworkReply*))},
{"isAutoInfer", true}
}
},
...
4. 源代码:
想深入了解该库,可以查看源代码学习,查看历史文章或和作者沟通了解该库的介绍原理,相信会对你的网络编程有所帮助.
(1) 源码地址(不定期更新):
https://github.com/aeagean/QtNetworkService
(2) 使用该库的应用:
https://github.com/aeagean/QtKugouApi