Qt 移動應用推送通知實現

推送通知是移動應用提升用戶粘性的核心功能——無論是即時消息提醒、活動推送還是狀態更新,都需要通過推送功能觸達用戶。Qt雖未直接提供跨平臺推送API,但可通過集成原生服務(如Firebase Cloud Messaging、Apple Push Notification service)實現全平臺推送。本文從原理到實戰,詳解Qt移動應用推送通知的完整實現方案,覆蓋Android和iOS雙平臺。

一、推送通知核心原理與架構

移動應用的推送通知需要依托平臺級服務,核心架構如下:

┌─────────────┐     ┌──────────────┐     ┌──────────────┐     ┌─────────────┐
│  你的服務器  │────?│ 平臺推送服務  │────?│ 移動設備系統  │────?│ 你的Qt應用  │
└─────────────┘     └──────────────┘     └──────────────┘     └─────────────┘(FCM/APNs等)        (系統通知托盤)

1. 關鍵概念

  • 設備令牌(Token):每個設備上的應用實例會生成唯一令牌,用于標識接收終端(如FCM的registration token、APNs的device token);
  • 推送服務
    • Android:依賴Firebase Cloud Messaging(FCM);
    • iOS:依賴Apple Push Notification service(APNs);
  • 通知類型
    • 顯示通知:包含標題、內容、圖標等,由系統托盤展示;
    • 數據通知:無UI展示,直接傳遞數據給應用(需應用運行)。

二、Android平臺:基于FCM的推送實現

1. 環境準備

(1)配置Firebase項目
  1. 訪問Firebase控制臺,創建項目并添加Android應用;
  2. 下載配置文件google-services.json,復制到Qt項目的android目錄下;
  3. 在Firebase控制臺啟用“Cloud Messaging”服務。
(2)Qt項目配置

.pro文件中添加Android權限和依賴:

QT += androidextras# 權限配置
android {ANDROID_PACKAGE_SOURCE_DIR = $$PWD/androidandroidPermissions += \android.permission.INTERNET \com.google.android.c2dm.permission.RECEIVE \android.permission.WAKE_LOCK
}

2. 核心代碼實現

(1)獲取設備令牌(Token)

通過JNI調用Android原生API獲取FCM令牌:

// FCMHelper.h
#ifndef FCMHELPER_H
#define FCMHELPER_H#include <QObject>
#include <QAndroidJniObject>class FCMHelper : public QObject {Q_OBJECT
public:explicit FCMHelper(QObject *parent = nullptr);void getToken();signals:void tokenReceived(const QString &token); // 令牌獲取成功void tokenError(const QString &error);    // 令牌獲取失敗private slots:void onTokenReceived(JNIEnv *env, jobject thiz, jstring token);void onTokenError(JNIEnv *env, jobject thiz, jstring error);
};#endif // FCMHELPER_H
// FCMHelper.cpp
#include "FCMHelper.h"
#include <QtAndroid>
#include <QDebug>// JNI回調函數注冊
static JNINativeMethod methods[] = {{"onTokenReceived", "(Ljava/lang/String;)V", (void*)&FCMHelper::onTokenReceived},{"onTokenError", "(Ljava/lang/String;)V", (void*)&FCMHelper::onTokenError}
};jint JNI_OnLoad(JavaVM* vm, void* reserved) {JNIEnv* env;if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK)return JNI_ERR;jclass cls = env->FindClass("org/qtproject/example/FCMReceiver");env->RegisterNatives(cls, methods, sizeof(methods)/sizeof(methods[0]));return JNI_VERSION_1_6;
}FCMHelper::FCMHelper(QObject *parent) : QObject(parent) {// 初始化FCM服務QAndroidJniObject activity = QtAndroid::androidActivity();QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/FCMReceiver","initialize","(Landroid/app/Activity;)V",activity.object<jobject>());
}void FCMHelper::getToken() {// 調用Java方法獲取令牌QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/FCMReceiver","getToken");
}// 令牌獲取成功的JNI回調
void FCMHelper::onTokenReceived(JNIEnv *env, jobject thiz, jstring token) {QString tokenStr = env->GetStringUTFChars(token, nullptr);qDebug() << "FCM Token:" << tokenStr;emit tokenReceived(tokenStr);
}// 令牌獲取失敗的JNI回調
void FCMHelper::onTokenError(JNIEnv *env, jobject thiz, jstring error) {QString errorStr = env->GetStringUTFChars(error, nullptr);qDebug() << "FCM Error:" << errorStr;emit tokenError(errorStr);
}
(2)創建Android原生接收類

android/src/org/qtproject/example/目錄下創建FCMReceiver.java

package org.qtproject.example;import android.app.Activity;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;public class FCMReceiver extends FirebaseMessagingService {private static Activity m_activity;private static native void onTokenReceived(String token);private static native void onTokenError(String error);public static void initialize(Activity activity) {m_activity = activity;}public static void getToken() {FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> {if (!task.isSuccessful()) {onTokenError("獲取令牌失敗: " + task.getException().getMessage());return;}String token = task.getResult();onTokenReceived(token);});}// 接收推送消息@Overridepublic void onMessageReceived(RemoteMessage remoteMessage) {Log.d("FCM", "收到推送消息");if (remoteMessage.getNotification() != null) {// 處理顯示通知String title = remoteMessage.getNotification().getTitle();String body = remoteMessage.getNotification().getBody();showNotification(title, body);}if (remoteMessage.getData().size() > 0) {// 處理數據通知(可發送到Qt應用)String data = remoteMessage.getData().toString();// 調用Qt方法傳遞數據(需通過JNI)}}// 顯示系統通知private void showNotification(String title, String body) {// Android通知欄顯示邏輯(需創建通知渠道)// ...}
}
(3)在Qt應用中使用
// 主窗口中初始化FCM
FCMHelper *fcmHelper = new FCMHelper(this);
connect(fcmHelper, &FCMHelper::tokenReceived, this, [this](const QString &token) {// 將令牌發送到你的服務器sendTokenToServer(token);
});
fcmHelper->getToken();

三、iOS平臺:基于APNs的推送實現

1. 環境準備

(1)配置Apple開發者賬號
  1. 在Apple開發者中心創建推送證書(APNs SSL Certificate);
  2. 在Xcode中配置項目:開啟“Push Notifications”能力,導入推送證書。
(2)Qt項目配置

.pro文件中添加iOS配置:

ios {QMAKE_INFO_PLIST = Info.plistiosDeploymentTarget = 12.0
}

Info.plist中添加推送權限描述:

<key>NSRemoteNotificationUsageDescription</key>
<string>需要推送通知權限以接收消息提醒</string>

2. 核心代碼實現

(1)請求推送權限并獲取設備令牌

通過Objective-C++調用iOS原生API:

// APNsHelper.h
#ifndef APNHELPER_H
#define APNHELPER_H#include <QObject>
#include <QString>#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
#endifclass APNsHelper : public QObject {Q_OBJECT
public:explicit APNsHelper(QObject *parent = nullptr);void requestPermission();signals:void tokenReceived(const QString &token);void permissionDenied();private:
#ifdef __OBJC__void registerForRemoteNotifications();
#endif
};#endif // APNHELPER_H
// APNsHelper.mm(注意文件后綴為.mm以支持Objective-C++)
#include "APNsHelper.h"
#include <QDebug>#ifdef __OBJC__
// 通知代理類
@interface QtAPNsDelegate : NSObject <UNUserNotificationCenterDelegate>
@property (nonatomic, assign) APNsHelper *helper;
@end@implementation QtAPNsDelegate
- (void)userNotificationCenter:(UNUserNotificationCenter *)centerwillPresentNotification:(UNNotification *)notificationwithCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {// 應用前臺時顯示通知completionHandler(UNNotificationPresentationOptionBanner | UNNotificationPresentationOptionSound);
}- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)responsewithCompletionHandler:(void(^)(void))completionHandler {// 處理通知點擊事件completionHandler();
}
@end
#endifAPNsHelper::APNsHelper(QObject *parent) : QObject(parent) {
#ifdef __OBJC__// 設置通知代理QtAPNsDelegate *delegate = [[QtAPNsDelegate alloc] init];delegate.helper = this;UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];center.delegate = delegate;
#endif
}void APNsHelper::requestPermission() {
#ifdef __OBJC__UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert |UNAuthorizationOptionSound |UNAuthorizationOptionBadge)completionHandler:^(BOOL granted, NSError *error) {if (granted) {[self registerForRemoteNotifications];} else {emit permissionDenied();}}];
#endif
}#ifdef __OBJC__
void APNsHelper::registerForRemoteNotifications() {dispatch_async(dispatch_get_main_queue(), ^{[[UIApplication sharedApplication] registerForRemoteNotifications];});
}
#endif// 重寫UIApplicationDelegate的方法獲取令牌(需在main.m中實現)
#ifdef __OBJC__
extern "C" void applicationDidRegisterForRemoteNotificationsWithDeviceToken(UIApplication *application, NSData *deviceToken) {// 轉換token為字符串const unsigned char *dataBuffer = (const unsigned char *)[deviceToken bytes];NSMutableString *tokenString = [NSMutableString stringWithCapacity:[deviceToken length] * 2];for (int i = 0; i < [deviceToken length]; ++i) {[tokenString appendFormat:@"%02.2hhx", dataBuffer[i]];}// 發送令牌到Qt信號APNsHelper *helper = ...; // 獲取APNsHelper實例emit helper->tokenReceived([tokenString UTF8String]);
}
#endif
(2)在Qt應用中使用
// 初始化APNs
#ifdef Q_OS_IOS
APNsHelper *apnsHelper = new APNsHelper(this);
connect(apnsHelper, &APNsHelper::tokenReceived, this, [this](const QString &token) {sendTokenToServer(token); // 發送令牌到服務器
});
apnsHelper->requestPermission();
#endif

四、跨平臺封裝與統一接口

為簡化雙平臺開發,可封裝統一的推送管理類:

// PushManager.h
#ifndef PUSHMANAGER_H
#define PUSHMANAGER_H#include <QObject>
#include <QString>class PushManager : public QObject {Q_OBJECT
public:static PushManager *instance();void initialize(); // 初始化推送服務void sendTokenToServer(const QString &token); // 上傳令牌到服務器signals:void notificationReceived(const QString &title, const QString &content); // 收到通知void tokenReady(const QString &token); // 令牌就緒private:PushManager(QObject *parent = nullptr);
};#endif // PUSHMANAGER_H
// PushManager.cpp
#include "PushManager.h"
#ifdef Q_OS_ANDROID
#include "FCMHelper.h"
#endif
#ifdef Q_OS_IOS
#include "APNsHelper.h"
#endif
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>PushManager *PushManager::instance() {static PushManager instance;return &instance;
}PushManager::PushManager(QObject *parent) : QObject(parent) {}void PushManager::initialize() {
#ifdef Q_OS_ANDROIDFCMHelper *fcm = new FCMHelper(this);connect(fcm, &FCMHelper::tokenReceived, this, &PushManager::tokenReady);fcm->getToken();
#endif
#ifdef Q_OS_IOSAPNsHelper *apns = new APNsHelper(this);connect(apns, &APNsHelper::tokenReceived, this, &PushManager::tokenReady);apns->requestPermission();
#endif
}void PushManager::sendTokenToServer(const QString &token) {// 發送POST請求到你的服務器,注冊令牌QNetworkAccessManager *manager = new QNetworkAccessManager(this);QNetworkRequest request(QUrl("https://你的服務器地址/register_token"));request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");QByteArray data = QString("{\"token\":\"%1\"}").arg(token).toUtf8();QNetworkReply *reply = manager->post(request, data);connect(reply, &QNetworkReply::finished, [reply]() {if (reply->error() == QNetworkReply::NoError) {qDebug() << "令牌注冊成功";} else {qDebug() << "令牌注冊失敗:" << reply->errorString();}reply->deleteLater();});
}

main.cpp中初始化:

#include "PushManager.h"int main(int argc, char *argv[]) {QGuiApplication app(argc, argv);// 初始化推送服務PushManager::instance()->initialize();// ... 其他初始化代碼 ...return app.exec();
}

五、通知點擊處理與應用跳轉

當用戶點擊通知時,需打開應用并跳轉到對應頁面,實現方式如下:

1. Android處理

FCMReceiver.java中重寫通知點擊邏輯:

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {// ... 其他代碼 ...Intent intent = new Intent(this, org.qtproject.qt5.android.bindings.QtActivity.class);intent.putExtra("page", "detail"); // 傳遞頁面參數intent.putExtra("id", "123");      // 傳遞數據PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);// 構建通知時關聯PendingIntentNotificationCompat.Builder builder = new NotificationCompat.Builder(this, "channel_id").setContentIntent(pendingIntent);
}

在Qt中獲取參數:

// 從Android intent中獲取參數
#ifdef Q_OS_ANDROID
QAndroidJniObject activity = QtAndroid::androidActivity();
QAndroidJniObject intent = activity.callObjectMethod("getIntent", "()Landroid/content/Intent;");
QAndroidJniObject page = intent.callObjectMethod("getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;", QAndroidJniObject::fromString("page").object<jstring>());
if (page.isValid()) {QString pageStr = page.toString();qDebug() << "跳轉頁面:" << pageStr;// 執行頁面跳轉邏輯
}
#endif

2. iOS處理

QtAPNsDelegate中處理點擊事件:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)responsewithCompletionHandler:(void(^)(void))completionHandler {NSDictionary *userInfo = response.notification.request.content.userInfo;NSString *page = userInfo[@"page"];// 傳遞參數到Qt(可通過全局變量或信號)completionHandler();
}

六、最佳實踐與注意事項

1. 權限與用戶體驗

  • 權限申請時機:在用戶完成關鍵操作(如登錄)后再請求推送權限,提高授權率;
  • 頻率控制:避免頻繁推送,提供“設置→通知”開關允許用戶關閉;
  • 內容相關性:推送內容與用戶行為相關(如購物應用推送降價提醒)。

2. 技術優化

  • 令牌刷新處理:設備令牌可能會變化(如應用重裝、系統更新),需定期重新獲取并同步到服務器;
  • 通知渠道:Android 8.0+必須創建通知渠道,否則通知無法顯示:
    // Android創建通知渠道
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {NotificationChannel channel = new NotificationChannel("default", "默認通知", NotificationManager.IMPORTANCE_DEFAULT);NotificationManager manager = getSystemService(NotificationManager.class);manager.createNotificationChannel(channel);
    }
    
  • 后臺數據處理:數據通知(無UI)需在Service(Android)或AppDelegate(iOS)中處理,避免阻塞UI。

3. 測試工具

  • FCM測試:使用Firebase控制臺的“發送測試消息”功能;
  • APNs測試:使用curl命令發送測試通知:
    curl -v -d '{"aps":{"alert":"測試通知","sound":"default"}}' \
    -H "apns-topic: 你的應用Bundle ID" \
    -H "apns-push-type: alert" \
    --http2 \
    --cert 你的推送證書.pem:證書密碼 \
    https://api.sandbox.push.apple.com/3/device/設備令牌
    

七、總結

Qt移動應用的推送通知實現需針對Android和iOS平臺分別集成FCM和APNs服務,核心步驟包括:

  1. 配置平臺推送服務并獲取設備令牌;
  2. 將令牌同步到你的服務器,用于定向推送;
  3. 處理接收的通知并展示到系統托盤;
  4. 實現通知點擊跳轉邏輯。

通過封裝跨平臺接口,可顯著降低雙平臺開發的復雜度。實際開發中需重點關注令牌刷新、權限管理和用戶體驗,避免過度推送導致用戶反感。

掌握這套方案后,你的Qt移動應用將具備完善的推送能力,有效提升用戶活躍度和留存率。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/91303.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/91303.shtml
英文地址,請注明出處:http://en.pswp.cn/web/91303.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Word和WPS文字如何制作分欄試卷?想分幾欄分幾欄

使用Word和WPS文字制作試卷的時候&#xff0c;通常會使用A3大小的紙張&#xff0c;橫向布局。但是如果題目的題干、問題、選項文字太少&#xff0c;會帶來試卷上有較大的空白&#xff0c;既不美觀又浪費紙&#xff0c;解決辦法就是將試卷分欄&#xff0c;根據需要分成多欄&…

ubuntu 安裝vmware tools

VMware Workstation菜單欄->虛擬機->安裝VMware Tools 打開ubuntu內加載的光盤&#xff0c;復制VMwareTools-10.3.26-22085142.tar.gz&#xff0c;解壓出來 sudo ./vmware-install.pl #執行安裝軟件 VMware Tools 安裝完成以后重啟Ubuntu&#xff0c;重啟以后就可以直…

【實時Linux實戰系列】在實時應用中進行負載均衡

在實時應用中&#xff0c;負載均衡是確保系統能夠高效處理多個任務的關鍵技術。通過合理調度任務到不同的處理單元&#xff0c;負載均衡可以提高系統的整體性能&#xff0c;減少延遲&#xff0c;并提高資源利用率。在實時 Linux 系統中&#xff0c;負載均衡尤為重要&#xff0c…

bash的特性-命令和文件自動補全

一、前言在 Linux Shell 編程和日常使用中&#xff0c;Bash 的自動補全功能 是一個非常強大且實用的特性。它不僅可以節省輸入時間&#xff0c;還能有效減少拼寫錯誤&#xff0c;提升命令執行效率。本文將帶你全面了解 Bash 的自動補全機制&#xff0c;包括&#xff1a;? 命令…

Ubuntu系統 系統盤和數據盤擴容具體操作

Linux磁盤配置和需求&#xff0c;以下是完整的操作方案&#xff1a; 可以看到系統盤vda3 還有48GB 數據盤則是還有512GB沒有掛載使用&#xff0c;下面是完成數據擴容的具體操作 一、完成系統盤擴容&#xff08;使用98GB空間&#xff09; # 1. 擴展邏輯卷&#xff08;LVM架構&am…

從0到1學Pandas(七):Pandas 在機器學習中的應用

目錄一、數據預處理1.1 特征提取1.2 數據標準化與歸一化1.3 特征編碼二、特征工程2.1 特征選擇?2.2 特征組合與衍生?2.3 缺失值處理策略?三、模型訓練與評估3.1 數據集劃分3.2 模型訓練與預測3.3 模型評估與調優四、Pipeline 構建4.1 自動化工作流4.2 模型部署與應用4.3 模型…

LangChain和LangGraph 里面的 `create_react_agent`有什么不同

這兩個函數雖然名稱相同&#xff0c;但來自不同的庫&#xff08;LangChain 和 LangGraph&#xff09;&#xff0c;它們在實現和使用上有一些關鍵區別&#xff1a; 主要區別特性LangChain 的 create_react_agentLangGraph 的 create_react_agent所屬庫LangChainLangGraph設計目的…

PostgreSQL 與 Oracle 數據庫字段類型的詳細對比

一、數值類型對比數據類型OraclePostgreSQL說明整數NUMBER(p,0)SMALLINT/INT/BIGINTOracle 統一用 NUMBER&#xff0c;PG 區分精度范圍浮點數BINARY_FLOATREAL單精度浮點雙精度浮點BINARY_DOUBLEDOUBLE PRECISION雙精度浮點高精度小數NUMBER(p,s)NUMERIC(p,s)精確數值存儲自增序…

JVM 性能調優實戰:讓系統性能 “飛” 起來的核心策略

在 Java 應用的生命周期中&#xff0c;性能問題如同隱藏的 “暗礁”—— 初期可能不顯眼&#xff0c;但隨著用戶量增長和業務復雜度提升&#xff0c;微小的性能損耗會被無限放大&#xff0c;最終導致系統響應遲緩、頻繁卡頓甚至崩潰。JVM 性能調優的目標&#xff0c;就是通過優…

Android Handler 完全指南

在 Android 開發中&#xff0c;Handler 是線程通信的核心工具 —— 當你在子線程下載圖片后需要更新 UI&#xff0c;當你在 TCP 連接中收到數據需要通知界面&#xff0c;當你需要延遲執行某個任務時&#xff0c;都會用到 Handler。這個看似簡單的類&#xff0c;卻蘊含著 Androi…

梳理Ego-Planner模式下5通道、6通道與無人機模式的關系

Copilot said: 你需要梳理Ego-Planner模式下5通道、6通道與無人機模式的關系&#xff0c;以及軌跡跟隨、緊急情況和人工接管的流程。下面結合你的描述和三張圖片&#xff0c;對核心邏輯進行總結和整理&#xff1a; --- ## 一、狀態組合與對應模式&#xff08;見圖1&#xff09;…

odbc和jdbc什么區別

ODBC 和 JDBC 都是用于連接和操作數據庫的標準接口&#xff0c;但它們分別面向不同的編程語言和平臺。下面是它們的區別與對比&#xff0c;幫助你理解它們的用途和適用場景。&#x1f4ca; 一、基本概念對比特性ODBC&#xff08;Open Database Connectivity&#xff09;JDBC&am…

境外期貨Level2高頻Tick歷史行情數據獲取與應用指南

在金融量化分析中&#xff0c;本地數據的高效使用是提升策略效果的重要基礎。本文以CSV格式的本地數據為核心&#xff0c;以外盤期貨分鐘數據、CME/COMEX/CBOT歷史行情為例&#xff0c;闡述專業化的數據處理與應用方法&#xff0c;為研究者提供可行性方案。一、數據預處理標準化…

迅為RK3588開發板安卓GPIO調用-APP運行測試

將網盤上的安卓工程文件復制到 Windows 電腦上。確保工程路徑中使用英文字符&#xff0c;不包含中文。接著&#xff0c;啟動 Android Studio&#xff0c;點擊“Open”按鈕選擇應用工程文件夾&#xff0c;然后點擊“OK”。由于下載 Gradle 和各種 Jar 包可能需要一段時間&#x…

以太坊下一階段的關鍵——隱私

1. 引言 隨著以太坊慶祝其十周年紀念&#xff0c;Aztec Labs 聯合創始人兼 CEO Zac Williamson 和以太坊基金會 PSE 負責人 Sam Richards 表示&#xff0c;以太坊必須加強其對隱私的原始承諾。 以太坊慶祝十周年紀念&#xff0c;標志著智能合約、去中心化金融&#xff08;DeF…

CTFpwn學習筆記1-棧溢出

棧溢出通過寫入超出數組定義范圍的字符長度達到溢出&#xff0c;從而覆蓋棧上其余數據&#xff0c;覆蓋返回地址約等于控制程序執行流例如&#xff1a;經過ida反編譯后&#xff0c;發現這里要將v2的值修改為11.28125才能獲得flag&#xff0c;同時我們可以發現這里使用了gets這個…

使用 Android Studio 中的 Gemini,讓 Flutter 開發更便捷

作者 / Flutter 產品經理 Ander Dobo 及 Gemini in Android Studio 產品經理 Sandhya Mohan在 Android Studio 中創建 Android 應用的 Flutter 開發者將迎來一次重大的飛躍: Android Studio 中的 Gemini 已全面支持 Dart 和 Flutter 開發&#xff01;這意味著您可以直接在您青睞…

Deep Learning_ Foundations and Concepts-Springer (2024)【拜讀】前向編碼器20章

Diffusion Models 擴散模型 我們已經了解到&#xff0c;構建強大的生成模型的一種有效方法是&#xff1a;先引入一個關于潛在變量z的分布p(z)&#xff0c;然后使用深度神經網絡將z變換到數據空間x。由于神經網絡具有通用性&#xff0c;能夠將簡單固定的分布轉化為關于x的高度靈…

Spring全局異常處理最佳實踐

全局異常處理器詳解 什么是全局異常處理器&#xff1f; 全局異常處理器是Spring框架提供的統一異常處理機制&#xff0c;用于集中處理應用程序中所有控制器&#xff08;Controller&#xff09;層拋出的異常。它的核心價值在于&#xff1a; 統一異常處理&#xff1a;避免在每個C…

STL學習(十一、常用的算數算法和集合算法)

目錄 一、常用的算數算法 1.accmulate 2.fill 二、常用的集合算法 1.set_intersection 2.set_union 3.set_difference 一、常用的算數算法 包含頭文件為<numeric> 1.accmulate 函數原型 accmulate(iterator beg, iterator end, value) // 計算元素累計和 // …