【鴻蒙HarmonyOS】一文詳解華為的服務卡片

7.服務卡片

1.什么是卡片

Form Kit(卡片開發服務)提供一種界面展示形式,可以將應用的重要信息或操作前置到服務卡片(以下簡稱“卡片”),以達到服務直達、減少跳轉層級的體驗效果。卡片常用于嵌入到其他應用(當前被嵌入方即卡片使用方只支持系統應用,例如桌面)中作為其界面顯示的一部分,并支持拉起頁面、發送消息等基礎的交互能力。

2.卡片的一些配置參數

entry/src/main/resources/base/profile/form_config.json

3. 卡片的生命周期

//卡片生命周期
import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';export default class EntryFormAbility extends FormExtensionAbility {// 	卡片被創建時觸發onAddForm(want: Want) {// formBindingData:提供卡片數據綁定的能力,包括FormBindingData對象的創建、相關信息的描述// 獲取卡片 IDconst formId = want.parameters && want.parameters['ohos.extra.param.key.form_identity'].toString()return formBindingData.createFormBindingData({title: '獲取數據中~'});// Called to return a FormBindingData object.const formData = '';return formBindingData.createFormBindingData(formData);}// 卡片轉換成常態卡片時觸發onCastToNormalForm(formId: string) {// Called when the form provider is notified that a temporary form is successfully// converted to a normal form.}// 卡片被更新時觸發(調用 updateForm 時)onUpdateForm(formId: string) {// Called to notify the form provider to update a specified form.}// 卡片發起特定事件時觸發(message)onFormEvent(formId: string, message: string) {// Called when a specified message event defined by the form provider is triggered.}//卡片被卸載時觸發onRemoveForm(formId: string) {// Called to notify the form provider that a specified form has been destroyed.}// 卡片狀態發生改變時觸發onAcquireFormState(want: Want) {// Called to return a {@link FormState} object.return formInfo.FormState.READY;}
}

4.卡片的通信

1.卡片之間通信

卡片在創建時,會觸發onAddForm生命周期,此時返回數據可以直接傳遞給卡片

另外卡片在被卸載時,會觸發onRemoveForm生命周期

1.卡片創建時傳遞數據

2.卡片向卡片的生命周期通信

卡片頁面中可以通過postCardAction接口觸發message事件拉起FormExtensionAbility中的onUpdateForm

onUpdateForm中通過updateForm來返回數據

const localStorage = new LocalStorage()
// 卡片組件通過LocalStorage來接收onAddForm中返回的數據
@Entry(localStorage)
@Component
struct WidgetCard {// 接收onAddForm中返回的卡片Id@LocalStorageProp("formId")formId: string = "xxx"
@LocalStorageProp('num')
num:number=0build() {Column() {Button(this.formId)Text(`${this.num}`).fontSize(15)Button('點擊數字+100').onClick(() => {postCardAction(this, {action: 'message',// 提交過去的參數params: { num: this.num, aa: 200, formId: this.formId }})})}.width("100%").height("100%").justifyContent(FlexAlign.Center)}
}

記得要攜帶formId過去,因為返回數據時需要根據formId找到對應的卡片

//卡片生命周期
import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';
import { JSON } from '@kit.ArkTS';export default class EntryFormAbility extends FormExtensionAbility {// 	卡片被創建時觸發onAddForm(want: Want) {// formBindingData:提供卡片數據綁定的能力,包括FormBindingData對象的創建、相關信息的描述class FormData {// 每一張卡片創建時都會被分配一個唯一的idformId: string = want.parameters!['ohos.extra.param.key.form_identity'].toString();}let formData = new FormData()// console.log('測試',JSON.stringify(formData))// 返回數據給卡片return formBindingData.createFormBindingData(formData);}// 卡片轉換成常態卡片時觸發onCastToNormalForm(formId: string) {// Called when the form provider is notified that a temporary form is successfully// converted to a normal form.}// 卡片被更新時觸發(調用 updateForm 時)onUpdateForm(formId: string) {// Called to notify the form provider to update a specified form.console.log('測試','卡片更新了')}// 卡片發起特定事件時觸發(message)onFormEvent(formId: string, message: string) {//   接收到卡片通過message事件傳遞的數據// message {"num":0,"aa":200,"params":{"num":100,"aa":200},"action":"message"}interface IData {num: numberaa: number}interface IRes extends IData {params: IData,action: "message"formId: string}const params = JSON.parse(message) as IResconsole.log('測試',JSON.stringify(params))interface IRet {num: number}const data: IRet = {num: params.num + 100}const formInfo = formBindingData.createFormBindingData(data)console.log('測試',JSON.stringify(formInfo))// 返回數據給對應的卡片formProvider.updateForm(params.formId, formInfo)}//卡片被卸載時觸發onRemoveForm(formId: string) {// Called to notify the form provider that a specified form has been destroyed.}// 卡片狀態發生改變時觸發onAcquireFormState(want: Want) {// Called to return a {@link FormState} object.return formInfo.FormState.READY;}
}

當卡片組件發起message事件時,我們可以通過onFormEvent監聽到

數據接收要聲明對應的接口

formProvider.updateForm(params.formId, formInfo)更新卡片

2.卡片與應用之間的通信

1.router 通信

router事件的特定是會拉起應用,前臺會展示頁面,會觸發應用的onCreateonNewWant生命周期

我們可以利用這個特性做喚起特定頁面并且傳遞數據。

當觸發router事件時,

  1. 如果應用沒有在運行,便觸發 onCreate事件
  2. 如果應用正在運行,便觸發onNewWant事件
const localStorage = new LocalStorage()
// 卡片組件通過LocalStorage來接收onAddForm中返回的數據
@Entry(localStorage)
@Component
struct WidgetCard {// 接收onAddForm中返回的卡片Id@LocalStorageProp("formId")formId: string = "xxx"
@LocalStorageProp('num')
num:number=0build() {Column() {//卡片與卡片的聲明周期Button(this.formId)Text(`${this.num}`).fontSize(15)Button('點擊數字+100').onClick(() => {postCardAction(this, {action: 'message',// 提交過去的參數params: { num: this.num, aa: 200, formId: this.formId }})})//router通信Button("跳轉到主頁").margin({top:10}).onClick(() => {postCardAction(this, {action: 'router',abilityName: 'EntryAbility', // 只能跳轉到當前應用下的UIAbilityparams: {targetPage: 'pages-3路由與axios/Index',}});})}.width("100%").height("100%").justifyContent(FlexAlign.Center)}
}

解析傳遞過來的卡片 id 與卡片的參數

分別在應用的onCreate和onNewWant編寫邏輯實現跳轉頁面

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { display, router, window } from '@kit.ArkUI';
import { formInfo } from '@kit.FormKit';export default class EntryAbility extends UIAbility {// 要跳轉的頁面 默認是首頁targetPage: string = "pages/Demo"onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {// 判斷是否帶有formId 因為我們直接點擊圖標,也會拉起應用,此時不會有formIdif (want.parameters && want.parameters[formInfo.FormParam.IDENTITY_KEY] !== undefined) {// 獲取卡片的formIdconst formId = want.parameters![formInfo.FormParam.IDENTITY_KEY].toString();// 獲取卡片傳遞過來的參數interface IData {targetPage: string}const params: IData = (JSON.parse(want.parameters?.params as string))console.log('測試','應用沒有運行')this.targetPage = params.targetPage//   我們也可以在這里通過 updateForm(卡片id,數據) 來返回內容給卡片}}// 如果應用已經在運行,卡片的router事件不會再觸發onCreate,會觸發onNewWantonNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {const formId = want.parameters![formInfo.FormParam.IDENTITY_KEY].toString();// 獲取卡片傳遞過來的參數interface IData {targetPage: string}const params: IData = (JSON.parse(want.parameters?.params as string))this.targetPage = params.targetPageconsole.log('測試','應用已經在運行')// 跳轉頁面router.pushUrl({url: this.targetPage})//   我們也可以在這里通過 updateForm(卡片id,數據) 來返回內容給卡片}onDestroy(): void {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');}onWindowStageCreate(windowStage: window.WindowStage): void {//模擬器啟動windowStage.loadContent(this.targetPage, (err) => {console.log('測試',this.targetPage)});}onWindowStageDestroy(): void {// Main window is destroyed, release UI related resourceshilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');}onForeground(): void {// Ability has brought to foregroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');}onBackground(): void {// Ability has back to backgroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');}
}

2.call 通信

call會拉起應用,但是會在后臺的形式運行。需要申請后臺運行權限,可以進行比較耗時的任務

需要申請后臺運行應用權限

{"module": {// ..."requestPermissions": [{"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"}],
  1. 卡片組件觸發call事件,參數中必須攜帶method屬性,用來區分不同的方法
export const localStorage = new LocalStorage()@Entry(localStorage)
@Component
struct WidgetCard {// 接收onAddForm中返回的卡片Id@LocalStorageProp("formId")formId: string = "xxx"@LocalStorageProp("num")num: number = 100build() {Column() {Button("call事件" + this.num).onClick(() => {postCardAction(this, {action: 'call',abilityName: 'EntryAbility', // 只能跳轉到當前應用下的UIAbilityparams: {// 如果事件類型是call,必須傳遞method屬性,用來區分不同的事件method: "inc",formId: this.formId,num: this.num,}});})}.width("100%").height("100%").justifyContent(FlexAlign.Center)}
}
  1. 應用EntryAbility在onCreate中,通過 callee來監聽不同的method事件
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { router, window } from '@kit.ArkUI';
import { formBindingData, formInfo, formProvider } from '@kit.FormKit';
import { rpc } from '@kit.IPCKit';// 占位 防止語法出錯,暫無實際作用
class MyParcelable implements rpc.Parcelable {marshalling(dataOut: rpc.MessageSequence): boolean {return true}unmarshalling(dataIn: rpc.MessageSequence): boolean {return true}
}export default class EntryAbility extends UIAbility {// 要跳轉的頁面 默認是首頁targetPage: string = "pages/Index"onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {//   監聽call事件中的特定方法this.callee.on("inc", (data: rpc.MessageSequence) => {// data中存放的是我們的參數params: {// 如果事件類型是call,必須傳遞method屬性,用來區分不同的事件// method: "inc",// formId: this.formId,// num: this.num,interface IRes {formId: stringnum: number}// 讀取參數const params = JSON.parse(data.readString() as string) as IResinterface IData {num: number}// 修改數據const info: IData = {num: params.num + 100}// 響應數據const dataInfo = formBindingData.createFormBindingData(info)formProvider.updateForm(params.formId, dataInfo)}// 防止語法報錯,暫無實際應用return new MyParcelable()})}onWindowStageCreate(windowStage: window.WindowStage): void {// 跳轉到對應的頁面windowStage.loadContent(this.targetPage, (err) => {if (err.code) {return;}});}onForeground(): void {// Ability has brought to foregroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');}onBackground(): void {// Ability has back to backgroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');}
}

5.卡片與圖片的通信

1.傳遞本地圖片

import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo } from '@kit.CoreFileKit';
import { promptAction } from '@kit.ArkUI';@Entry
@Component
struct Index {async aboutToAppear() {//-------------------------------------------------------------- 1.初始化圖片配置項// 創建一個新的 PhotoSelectOptions 實例來配置圖片選擇器的行為let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();// 設置 MIME 類型為圖像類型,這樣用戶只能選擇圖像文件PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;// 設置用戶可以選擇的最大圖片數量為 1 張PhotoSelectOptions.maxSelectNumber = 1;//----------------------------------------------------------- 2.打開圖片選擇器,拿到圖片// 創建一個新的 PhotoViewPicker 實例,用于打開圖片選擇器let photoPicker = new photoAccessHelper.PhotoViewPicker();// 使用前面配置好的選項打開圖片選擇器,并等待用戶完成選擇// 注意這里的 select 方法是一個異步方法,所以需要使用 await 關鍵字等待其結果const PhotoSelectResult = await photoPicker.select(PhotoSelectOptions);// 獲取用戶選擇的第一張圖片的 URI(統一資源標識符)// 假設這里只關心用戶選擇的第一張圖片// uri file://media/Photo/3/IMG_1729864738_002/screenshot_20241025_215718.jpgconst uri = PhotoSelectResult.photoUris[0];promptAction.showToast({ message: `${uri}` })//------------------------------------------------------------- 3.拷貝圖片到臨時目錄// 獲取應用的臨時目錄let tempDir = getContext(this).getApplicationContext().tempDir;// 生成一個新的文件名const fileName = 123 + '.png'// 通過緩存路徑+文件名 拼接出完整的路徑const copyFilePath = tempDir + '/' + fileName// 將文件 拷貝到 臨時目錄const file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY)fileIo.copyFileSync(file.fd, copyFilePath)}build() {RelativeContainer() {}.height('100%').width('100%')}
}

一旦保存到本地緩存除非卸載應用不然就一直有的

import { Want } from '@kit.AbilityKit';
import { fileIo } from '@kit.CoreFileKit';
import { formBindingData, FormExtensionAbility } from '@kit.FormKit';export default class EntryFormAbility extends FormExtensionAbility {// 在添加卡片時,打開一個本地圖片并將圖片內容傳遞給卡片頁面顯示onAddForm(want: Want): formBindingData.FormBindingData {// 假設在當前卡片應用的tmp目錄下有一個本地圖片 123.pnglet tempDir = this.context.getApplicationContext().tempDir;let imgMap: Record<string, number> = {};// 打開本地圖片并獲取其打開后的fdlet file = fileIo.openSync(tempDir + '/' + '123.png');//file.fd 打開的文件描述符。imgMap['imgBear'] = file.fd;class FormDataClass {// 卡片需要顯示圖片場景, 必須和下列字段formImages 中的key 'imgBear' 相同。imgName: string = 'imgBear';// 卡片需要顯示圖片場景, 必填字段(formImages 不可缺省或改名), 'imgBear' 對應 fdformImages: Record<string, number> = imgMap;}let formData = new FormDataClass();console.log("formDataformData", JSON.stringify(formData))// 將fd封裝在formData中并返回至卡片頁面return formBindingData.createFormBindingData(formData);}
}
let storageWidgetImageUpdate = new LocalStorage();@Entry(storageWidgetImageUpdate)
@Component
struct WidgetCard {@LocalStorageProp('imgName') imgName: ResourceStr = "";build() {Column() {Text(this.imgName)}.width('100%').height('100%').backgroundImage('memory://' + this.imgName).backgroundImageSize(ImageSize.Cover)}
}

Image組件通過入參(memory://fileName)中的(memory://)標識來進行遠端內存圖片顯示,其中fileName需要和EntryFormAbility傳遞對象('formImages': {key: fd})中的key相對應。

2.傳遞網絡圖片

import { Want } from '@kit.AbilityKit';
import { fileIo } from '@kit.CoreFileKit';
import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';export default class EntryFormAbility extends FormExtensionAbility {// 將網絡圖片傳遞給onAddForm(want: Want) {// 注意:FormExtensionAbility在觸發生命周期回調時被拉起,僅能在后臺存在5秒// 建議下載能快速下載完成的小文件,如在5秒內未下載完成,則此次網絡圖片無法刷新至卡片頁面上const formId = want.parameters![formInfo.FormParam.IDENTITY_KEY] as string// 需要在此處使用真實的網絡圖片下載鏈接let netFile ='https://env-00jxhf99mujs.normal.cloudstatic.cn/card/3.webp?expire_at=1729871552&er_sign=0eb3f6ac3730703039b1565b6d3e59ad'; let httpRequest = http.createHttp()// 下載圖片httpRequest.request(netFile).then(async (data) => {if (data?.responseCode == http.ResponseCode.OK) {// 拼接圖片地址let tempDir = this.context.getApplicationContext().tempDir;let fileName = 'file' + Date.now();let tmpFile = tempDir + '/' + fileName;let imgMap: Record<string, number> = {};class FormDataClass {// 卡片需要顯示圖片場景, 必須和下列字段formImages 中的key fileName 相同。imgName: string = fileName;// 卡片需要顯示圖片場景, 必填字段(formImages 不可缺省或改名), fileName 對應 fdformImages: Record<string, number> = imgMap;}// 打開文件let imgFile = fileIo.openSync(tmpFile, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);imgMap[fileName] = imgFile.fd;// 寫入文件await fileIo.write(imgFile.fd, data.result as ArrayBuffer);let formData = new FormDataClass();let formInfo = formBindingData.createFormBindingData(formData);// 下載完網絡圖片后,再傳遞給卡片formProvider.updateForm(formId, formInfo)fileIo.closeSync(imgFile);httpRequest.destroy();console.log("============")}}).catch((e: BusinessError) => {console.log("eeee", e.message)})class FormData {formId: string = ""}// 先返回基本數據return formBindingData.createFormBindingData(new FormData);}onFormEvent(formId: string, message: string): void {}
}

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

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

相關文章

探索目標檢測:邊界框與錨框的奧秘

筆者在2022年開始學習目標檢測的時候&#xff0c;對各種框的概念那是相當混淆&#xff0c;比如&#xff1a; 中文名詞&#xff1a;邊界框、錨框、真實框、預測框等英文名詞&#xff1a;BoundingBox、AnchorBox、Ground Truth等 同一個英文名詞比如BoundingBox翻譯成中文也有多個…

[原創](現代Delphi 12指南):[macOS 64bit App開發]: [1]如何使用原生NSAlert消息框 (runModal模式)

[作者] 常用網名: 豬頭三 出生日期: 1981.XX.XX 企鵝交流: 643439947 個人網站: 80x86匯編小站 編程生涯: 2001年~至今[共24年] 職業生涯: 22年 開發語言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 開發工具: Visual Studio、Delphi、XCode、…

LangChain的向量RAG與MCP在意圖識別的主要區別

LangChain的向量RAG與MCP在意圖識別實現上的區別主要體現在技術路徑、流程設計以及應用場景三個方面&#xff1a; 1. 技術路徑差異 LangChain向量RAG 語義相似度驅動&#xff1a;通過用戶輸入的原始查詢與向量化知識庫的語義匹配實現意圖識別。例如&#xff0c;用戶提問"…

[特殊字符] Spring Cloud 微服務配置統一管理:基于 Nacos 的最佳實踐詳解

在微服務架構中&#xff0c;配置文件眾多、管理復雜是常見問題。本文將手把手演示如何將配置集中托管到 Nacos&#xff0c;并在 Spring Cloud Alibaba 項目中實現統一配置管理 自動刷新機制。 一、為什么要使用 Nacos 統一配置&#xff1f; 傳統方式下&#xff0c;每個服務都…

2025平航杯—團隊賽

2025平航杯團隊賽 計算機取證 分析起早王的計算機檢材&#xff0c;起早王的計算機插入過USB序列號是什么(格式&#xff1a;1)分析起早王的計算機檢材&#xff0c;起早王的便簽里有幾條待干(格式&#xff1a;1)分析起早王的計算機檢材&#xff0c;起早王的計算機默認瀏覽器是什…

JSON-RPC 2.0 規范中文版——無狀態輕量級遠程過程調用協議

前言 JSON-RPC是一種簡單、輕量且無狀態的遠程過程調用&#xff08;RPC&#xff09;協議&#xff0c;它允許不同系統通過標準化的數據格式進行通信。自2010年由JSON-RPC工作組發布以來&#xff0c;已成為眾多應用中實現遠程交互的基礎協議之一。本規范主要表達了JSON-RPC 2.0版…

微控制器編程 | ISP、IAP 與 ICP 的原理與比較

注&#xff1a;英文引文&#xff0c;機翻未校。 圖片清晰度限于引文原狀。 Introduction to Programming of Microcontroller: ISP, IAP and ICP 微控制器編程介紹&#xff1a;ISP、IAP 和 ICP Date: 30-11-2022 1. What is Microcontroller Programming 什么是微控制器編…

Allegro23.1新功能之新型via structure創建方法操作指導

Allegro23.1新功能之新型via structure創建方法操作指導 Allegro升級到了23.1后,支持創建新型via structure 通過直接定義參數來生成 具體操作如下 打開軟件,選擇 Allegro PCB Designer

IBM WebSphere Application Server 7.0/8.5.5證書過期問題處理

證書過期錯誤日志&#xff1a; [3/14/16 7:22:20:332 PDT] 0000007d WSX509TrustMa E CWPKI0312E: The certificate with subject DN CNMXSYSTEMS, OUctgNodeCell01, OUctgNode01, OIBM, CUS has an end date Mon Jan 11 11:17:18 PST 2016 which is no longer valid. [3/14/…

select,poll,epoll區別聯系

selsect,poll,epoll區別聯系 目錄 一、區別 二、聯系 select、poll 和 epoll 都是在 Linux 系統中用于實現 I/O 多路復用的機制&#xff0c;它們的主要目的是讓程序能夠同時監控多個文件描述符&#xff0c;以判斷是否有事件發生&#xff0c;從而提高 I/O 操作的效率。 一、區…

curl和wget的使用介紹

目錄 一、curl 和 wget 區別 二、wget的使用 2.1 參數說明 2.2 wget 使用示例 三、curl的使用 3.1 參數說明 3.2 curl使用示例 一、curl 和 wget 區別 wget 和 curl 都可以下載內容。它們都可以向互聯網發送請求并返回請求項&#xff0c;可以是文件、圖片或者是其他諸如…

日語學習-日語知識點小記-構建基礎-JLPT-N4階段(12): ておき ます

日語學習-日語知識點小記-構建基礎-JLPT-N4階段&#xff08;12&#xff09;&#xff1a; ておき ます。 1、前言&#xff08;1&#xff09;情況說明&#xff08;2&#xff09;工程師的信仰 2、知識點&#xff08;1&#xff09;&#xff5e;ておき ます。&#xff08;2&#x…

高質量水火焰無損音效包

今天設計寶藏給大家分享的是Cinematic Elements: Fire & Water音頻資源庫包含大量高質量的火焰和水的聲音效果。它具有非常強烈的個性特征和次世代的音效。火焰和水是兩個令人印象深刻而 interessing 的元素。它們的表現形式從微小無害到巨大毀滅性都有。因此,它們的聲音特…

畢業論文 | 傳統特征點提取算法與匹配算法對比分析

傳統特征點提取算法與匹配算法對比分析 一、特征點提取算法對比二、特征匹配算法對比三、核心算法原理與公式1. **Harris角點檢測**2. **SIFT描述子生成**3. **ORB描述子**四、完整Matlab代碼示例1. **Harris角點檢測與匹配**2. **SIFT特征匹配(需VLFeat庫)**3. **ORB特征匹配…

【網絡原理】從零開始深入理解HTTP的報文格式(二)

本篇博客給大家帶來的是網絡HTTP協議的知識點, 續上篇文章,接著介紹HTTP的報文格式. &#x1f40e;文章專欄: JavaEE初階 &#x1f680;若有問題 評論區見 ? 歡迎大家點贊 評論 收藏 分享 如果你不知道分享給誰,那就分享給薯條. 你們的支持是我不斷創作的動力 . 王子,公主請閱…

Microsoft .NET Framework 3.5 離線安裝包 下載

Microsoft. NET Framework 3.5 是支持生成和運行下一代應用程序和XML Web Services 的內部Windows 組件&#xff0c; 對 .NET Framework 2.0 和 3.0 中的許多新功能進行了更新和增補&#xff0c; 且附帶了 .NET Framework 2.0 Service Pack 1 和 .NET Framework 3.0 Service…

Flask + ajax上傳文件(三)--圖片上傳與OCR識別

本教程將詳細介紹如何使用Flask框架構建一個圖片上傳與文字識別(OCR)的Web應用。我們將使用EasyOCR作為OCR引擎,實現一個支持中文和英文識別的完整應用。 環境準備 首先,確保你已經安裝了Python 3.7+環境,然后安裝必要的依賴庫: pip install flask easyocr pillow werkz…

模型部署技巧(一)

模型部署技巧&#xff08;一&#xff09; 以下內容是參考CUDA與TensorRT模型部署內容第六章&#xff0c;主要針對圖像的前/后處理中的trick。 參考&#xff1a; 1.部署分類器-int8-calibration 2. cudnn安裝地址 3. 如何查找Tensor版本&#xff0c;與cuda 和 cudnn匹配 4. ti…

MySQL--數據引擎詳解

存儲引擎 MySQL體系結構 連接層&#xff1a; 主要接收客戶端的連接&#xff0c;然后完成一些鏈接的處理&#xff0c;以及認證授權的相關操作和安全方案&#xff0c;還要去檢查是否超過最大連接數等等&#xff0c;比如在連接MySQL服務器時需要輸入用戶名&#xff0c;密碼&#…

【含文檔+PPT+源碼】基于微信小程序的健康飲食食譜推薦平臺的設計與實現

項目介紹 本課程演示的是一款基于微信小程序的健康飲食食譜推薦平臺的設計與實現&#xff0c;主要針對計算機相關專業的正在做畢設的學生與需要項目實戰練習的 Java 學習者。 1.包含&#xff1a;項目源碼、項目文檔、數據庫腳本、軟件工具等所有資料 2.帶你從零開始部署運行本…