下载完成后的QT回调及结果
QT Callback with result after download is completed
我有一个 QT 应用程序,其中几个不同的子组件需要从 Internet 获取数据。我想要一个 Network
class 来完成所有的网络交互,然后以某种方式通知调用者。我无法弄清楚如何使用插槽来做到这一点,所以我编写了一个回调解决方案:
void Network::downloadFile(QString& urlstr, const std::function<void (QString, QByteArray, QNetworkReply::NetworkError)>& callback) {
auto processDownload = [&]() {
QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender());
QByteArray result;
QString filename = reply->url().fileName();
if (reply->error() == QNetworkReply::NoError) { // Success
result = reply->readAll();
}
callback(filename, result, reply->error());
reply->deleteLater();
};
QNetworkReply *reply = nam_->get(QNetworkRequest(QUrl(urlstr)));
connect(reply, &QNetworkReply::downloadProgress, this, &Network::downloadProgress);
connect(reply, &QNetworkReply::finished, this, processDownload);
}
但是,一旦调用 callback
,我就会遇到段错误。我尝试了几种不同的方法来定义回调,即使它为空,它仍然会崩溃(主要是段错误,有时是错误的函数调用)。它被定义为:
std::function<void(QJsonObject, QNetworkReply::NetworkError)> f = std::bind(&MainWindow::onResult, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
我采取了类似 static_cast<parent_class*>(this->parent())->onResult(..)
的方式,但这并不是很好的解耦。我怎样才能以可以传递(或发信号给)任何通用 std::function?
的方式做到这一点
编辑:下载文件通常这样调用:
void MainWindow::DoNetworkRQ(QString url) {
std::function<void(QJsonObject, QNetworkReply::NetworkError)> f = std::bind(&MainWindow::onResult, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
network_.downloadFile(url, f);
}
这会导致段错误。我如何以 QT 方式执行此操作?
@chehrlic 是正确的,您正在创建一个在调用之前超出范围的回调函数。您的问题不需要以“Qt 方式”解决。但是信号和槽会起作用,所以我会告诉你如何。
首先,将信号连接到插槽:
void MainWindow::DoNetworkRQ(QString url) {
connect(&network_, &Network::someSignal, this, &MainWindow::onResult);
network_.downloadFile(url, f);
}
然后,当您的网络任务完成时发出信号:
void Network::downloadFile(QString& urlstr, const std::function<void (QString, QByteArray, QNetworkReply::NetworkError)>& callback) {
auto processDownload = [&]() {
QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender());
QByteArray result;
QString filename = reply->url().fileName();
if (reply->error() == QNetworkReply::NoError) { // Success
result = reply->readAll();
}
emit someSignal(filename, result, reply->error());
reply->deleteLater();
};
QNetworkReply *reply = nam_->get(QNetworkRequest(QUrl(urlstr)));
connect(reply, &QNetworkReply::downloadProgress, this, &Network::downloadProgress);
connect(reply, &QNetworkReply::finished, this, processDownload);
}
我有一个 QT 应用程序,其中几个不同的子组件需要从 Internet 获取数据。我想要一个 Network
class 来完成所有的网络交互,然后以某种方式通知调用者。我无法弄清楚如何使用插槽来做到这一点,所以我编写了一个回调解决方案:
void Network::downloadFile(QString& urlstr, const std::function<void (QString, QByteArray, QNetworkReply::NetworkError)>& callback) {
auto processDownload = [&]() {
QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender());
QByteArray result;
QString filename = reply->url().fileName();
if (reply->error() == QNetworkReply::NoError) { // Success
result = reply->readAll();
}
callback(filename, result, reply->error());
reply->deleteLater();
};
QNetworkReply *reply = nam_->get(QNetworkRequest(QUrl(urlstr)));
connect(reply, &QNetworkReply::downloadProgress, this, &Network::downloadProgress);
connect(reply, &QNetworkReply::finished, this, processDownload);
}
但是,一旦调用 callback
,我就会遇到段错误。我尝试了几种不同的方法来定义回调,即使它为空,它仍然会崩溃(主要是段错误,有时是错误的函数调用)。它被定义为:
std::function<void(QJsonObject, QNetworkReply::NetworkError)> f = std::bind(&MainWindow::onResult, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
我采取了类似 static_cast<parent_class*>(this->parent())->onResult(..)
的方式,但这并不是很好的解耦。我怎样才能以可以传递(或发信号给)任何通用 std::function?
编辑:下载文件通常这样调用:
void MainWindow::DoNetworkRQ(QString url) {
std::function<void(QJsonObject, QNetworkReply::NetworkError)> f = std::bind(&MainWindow::onResult, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
network_.downloadFile(url, f);
}
这会导致段错误。我如何以 QT 方式执行此操作?
@chehrlic 是正确的,您正在创建一个在调用之前超出范围的回调函数。您的问题不需要以“Qt 方式”解决。但是信号和槽会起作用,所以我会告诉你如何。
首先,将信号连接到插槽:
void MainWindow::DoNetworkRQ(QString url) {
connect(&network_, &Network::someSignal, this, &MainWindow::onResult);
network_.downloadFile(url, f);
}
然后,当您的网络任务完成时发出信号:
void Network::downloadFile(QString& urlstr, const std::function<void (QString, QByteArray, QNetworkReply::NetworkError)>& callback) {
auto processDownload = [&]() {
QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender());
QByteArray result;
QString filename = reply->url().fileName();
if (reply->error() == QNetworkReply::NoError) { // Success
result = reply->readAll();
}
emit someSignal(filename, result, reply->error());
reply->deleteLater();
};
QNetworkReply *reply = nam_->get(QNetworkRequest(QUrl(urlstr)));
connect(reply, &QNetworkReply::downloadProgress, this, &Network::downloadProgress);
connect(reply, &QNetworkReply::finished, this, processDownload);
}