主頁 > 移動端開發 > ImageKnife組件,讓小白也能輕松搞定圖片開發

ImageKnife組件,讓小白也能輕松搞定圖片開發

2022-04-29 08:38:05 移動端開發

本期我們給大家帶來的是開發者周黎生的分享,希望能給你的HarmonyOS開發之旅帶來啟發~

 

圖片是UI界面的重要元素之一, 圖片加載速度及效果直接影回應用體驗,ArkUI開發框架提供了豐富的影像處理能力,如影像解碼、影像編碼、影像編輯及基本的位圖操作等,滿足了開發者日常開發所需, 

 

但隨著產品需求的日益增長,基本的影像處理能力已不能勝任某些比較復雜的應用場景,如無法直接獲取快取圖片、無法配置占位圖、無法進行自定義PixelMap圖片變換等, 

 

為增強ArkUI開發框架的影像處理能力,ImageKnife組件應運而生,本期我們將為大家帶來ImageKnife的介紹, 

 

一、ImageKnife簡介


ImageKnife是一個參考Glide框架進行設計,并基于eTS語言實作的圖片處理組件,它可以讓開發者能輕松且高效地進行圖片開發, 

 

注:Glide是一個快速高效的圖片加載庫,注重于平滑的滾動,提供了易用的API,高性能、可擴展的圖片解碼管道,以及自動的資源池技術, 

 

  • 功能方面,ImageKnife提供了自定義圖片變換、占位圖等圖片處理能力,幾乎滿足了開發者進行圖片處理的一切需求, 
  • 性能方面,ImageKnife采用LRU策略實作二級快取,可靈活配置,有效減少記憶體消耗,提升了應用性能, 
  • 使用方面,ImageKnife封裝了一套完整的圖片加載流程,開發者只需根據ImageKnifeOption配置相關資訊即可完成圖片的開發,降低了開發難度,提升了開發效率,

 

如圖1所示,是ImageKnife加載圖片的整體流程, 

 

圖1 ImageKnife加載圖片整體流程

 

二、ImageKnife實作原理


下面我們將為大家介紹ImageKnife加載圖片程序中每個環節的實作原理,讓大家更深刻地認識ImageKnife組件,圖2是ImageKnife加載圖片的時序圖: 

 

圖2 ImageKnife加載圖片的時序圖

 

1. 用戶配置資訊


在加載圖片前,用戶需根據自身需求配置相應的引數,包括圖片路徑、圖片大小、占位圖及快取策略等,ImageKnife提供了RequestOption類,用于封裝用戶配置資訊的介面,如圖3所示列舉了部分介面供大家參考: 

 

圖3 用戶配置引數

 

通過ImageKnifeExecute()方法獲取用戶配置資訊,然后執行ImageKnife.call(request),正式啟動圖片加載任務,相關實作代碼如下: 

 

imageKnifeExecute() {
  // 首先需要確保獲取ImageKnife單例物件
  if(ImageKnife){
  }else{
    ImageKnife = globalThis.exports.default.data.imageKnife;
  }
  // 生成配置資訊requestOption
  let request = new RequestOption();
  // 配置必要資訊和回呼
  this.configNecessary(request);
  // 配置快取相關資訊   
  this.configCacheStrategy(request);
  // 配置顯示資訊和回呼 
  this.configDisplay(request);
  // 啟動ImageKnife執行請求
  ImageKnife.call(request);
}


2. 加載圖片


加載圖片程序是ImageKnife組件的核心部分,如圖4所示,包含占位圖填充、快取實作及圖片解碼三個環節,下面我們將為大家分別介紹每個環節的實作,

 

圖4圖片加載程序

 

(1) 占位圖填充

 

占位圖就是圖片加載程序中頁面上的過渡效果,通常表現形式是在頁面上待加載區域填充灰色的占位圖,可以使得頁面框架不會因為加載失敗而變形,ImageKnife提供了占位圖功能,開發者可在RequestOption中配置是否啟動占位圖任務, 

 

如圖5所示是占位圖作業流程,執行圖片加載任務后,占位圖會填充加載頁面,如果圖片決議成功則將頁面上填充的占位圖替換為待加載的圖片,如果圖片決議失敗,則將頁面上填充的占位圖替換為“圖片決議失敗占位圖”, 

 

圖5 占位圖作業流程

 

相關實作代碼如下:

 

// 占位圖決議成功
placeholderOnComplete(imageKnifeData: ImageKnifeData) {
// 主圖未加載成功,并且未加載失敗  顯示占位圖  主圖加載成功或者加載失敗后=>不展示占位圖
  if (!this.loadMainReady && !this.loadErrorReady && !this.loadThumbnailReady) {
        this.placeholderFunc(imageKnifeData)
  }
}
// 加載失敗 占位圖決議成功
errorholderOnComplete(imageKnifeData: ImageKnifeData) {
  // 如果有錯誤占位圖 先決議并保存在RequestOption中 等到加載失敗時候進行呼叫
  this.errorholderData = https://www.cnblogs.com/HarmonyOSDev/archive/2022/04/28/imageKnifeData;
  if (this.loadErrorReady) {
    this.errorholderFunc(imageKnifeData)
  }
}


(2) 快取實作

 

快取是圖片加載程序中最關鍵的環節,快取機制直接影響了圖片加載速度及圖片滾動效果,開發者可通過以下方法來靈活配置快取策略,

 

圖6 快取策略API

 

為了保障圖片的加載速度,ImageKnife通過使用Least Recently Used(最近最少使用)清空策略來實作記憶體快取及磁盤快取, 

 

如圖7所示,在圖片加載程序中,CPU會首先讀取記憶體快取中的資料,如果讀取到圖片資源則直接顯示圖片,否則讀取磁盤快取資料,如果在磁盤快取上仍然沒有讀取到資料,則可判定為該圖片為網路圖片,這時需要將網路圖片解碼后再進行顯示(后面章節會詳細介紹),并將解碼后的圖片檔案快取至磁盤, 

 

圖7 圖片快取程序

 

下面我們將分別介紹兩種快取機制的具體實作: 

 

① 記憶體快取

 

記憶體快取,就是指當前程式運行記憶體分配的臨時存盤器,當我們使用ImageKnife加載圖片時,這張圖片會被快取到記憶體當中,只要在它還沒從記憶體中被清除之前,下次再加載這張圖片都會直接從記憶體中讀取,而不用重新從網路或硬碟上讀取,大幅度提升圖片的加載效率, 

 

ImageKnife記憶體快取的實作,需控制最大空間(maxsize),以及目前占用空間(size),相關實作代碼如下:  

 

// 移除較少使用的快取資料
trimToSize(tempsize: number) {
  while (true) {
    if (tempsize < 0) {
      this.map.clear()
      this.size = 0
      break
    }
    if (this.size <= tempsize || this.map.isEmpty()) {
      break
    }
    var delkey = this.map.getFirstKey()
    this.map.remove(delkey)
    this.size--
  }
}
// 快取資料最大值
maxSize(): number{
  return this.maxsize
}
// 設定快取資料量最大值
resize(maxsize: number) {
  if (maxsize < 0) {
    throw new Error('maxsize <0 & maxsize invalid');
  }
  this.maxsize = maxsize
  this.trimToSize(maxsize)
}
// 清除快取
evicAll() {
  this.trimToSize(-1)
}

 

② 磁盤快取

 

默認情況下,磁盤快取的是解碼后的圖片檔案,需防止應用重復從網路或其他地方下載和讀取資料,ImageKnife磁盤快取的實作,主要依靠journal檔案對快取資料進行保存,保證程式磁盤快取內容的持久化問題, 

 

相關實作代碼如下: 

 

//讀取journal檔案的快取資料
readJournal(path: string) {
  var fileReader = new FileReader(path)
  var line: string = ''
  while (!fileReader.isEnd()) {
    line = fileReader.readLine()
    line = line.replace('\n', '').replace('\r', '')
    this.dealwithJournal(line)
  }
  this.fileUtils.deleteFile(this.journalPathTemp)
  this.trimToSize()
}
//根據LRU演算法洗掉多余快取資料
private trimToSize() {
  while (this.size > this.maxSize) {
    var tempkey: string = this.cacheMap.getFirstKey()
    var fileSize = this.fileUtils.getFileSize(this.dirPath + tempkey)
    if (fileSize > 0) {
      this.size = this.size - fileSize
    }
    this.fileUtils.deleteFile(this.dirPath + tempkey)
    this.cacheMap.remove(tempkey)
    this.fileUtils.writeData(this.journalPath, 'remove ' + tempkey + '\n')
  }
}
//清除所有disk快取資料
cleanCacheData() {
  var length = this.cacheMap.size()
  for (var index = 0; index < length; index++) {
    this.fileUtils.deleteFile(this.dirPath + this.cacheMap[index])
  }
  this.fileUtils.deleteFile(this.journalPath)
  this.cacheMap.clear()
  this.size = 0
}


(3) 圖片解碼

 

當我們使用ImageKnife去加載一張圖片的時候,并不是將原始圖片直接顯示出來,而是會進行圖片解碼后再顯示到頁面,圖片解碼就是將不同格式的圖片(包括JPEG、PNG、GIF、WebP、BMP)解碼成統一格式的PixelMap圖片檔案, 

 

ImageKnife的圖片解碼能力依賴的是ArkUI開發框架提供的ImageSource解碼能力,通過import image from '@ohos.multimedia.image'匯入ArkUI開發框架的圖片能力,并呼叫createImageSource()方法獲取,實作代碼如下: 

 

import image from '@ohos.multimedia.image'
export class TransformUtils {
  static centerCrop(buf: ArrayBuffer, outWidth: number, outHeihgt: number,
                    callback?: AsyncTransform<Promise<PixelMap>>) {
    // 創建媒體解碼imageSource
    var imageSource = image.createImageSource(buf as any);
    // 獲取圖片資訊
    imageSource.getImageInfo()
      .then((p) => {
        var sw;
        var sh;
        var scale;
        var pw = p.size.width;
        var ph = p.size.height;
        // 根據centerCrop規則控制縮放比例
        if (pw == outWidth && ph == outHeihgt) {
          sw = outWidth;
          sh = outHeihgt;
        } else {
          if (pw * outHeihgt > outWidth * ph) {
            scale = outHeihgt / ph;
          } else {
            scale = outWidth / pw;
          }
          sw = pw * scale;
          sh = ph * scale;
        }
        var options = {
          editable: true,
          rotate: 0,
          desiredRegion: { size: { width: sw, height: sh },
            x: pw / 2 - sw / 2,
            y: ph / 2 - sh / 2,
          },
        }
        if (callback) {
          // 回呼,創建相關配置pixelmap
          callback('', imageSource.createPixelMap(options));
        }
      })
      .catch((error) => {
        callback(error, null);
      })
  }
}


3. 顯示圖片


獲取到PixelMap解碼檔案后,接下來就是將它渲染到應用界面上,ImageKnife的圖片渲染能力依賴的是ArkUI開發框架提供的Image組件的渲染能力,由于eTS是宣告式的,我們無法直接獲得Image組件的物件,需要依賴ArkUI開發框架的@State能力系結輸入引數,在改變屬性物件之后,通知UI組件重新渲染,達到圖片顯示的效果, 

 

相關代碼如下: 

 

@Component
export struct ImageKnifeComponent {
  @Watch('watchImageKnifeOption') @Link imageKnifeOption: ImageKnifeOption;
  @State imageKnifePixelMapPack: PixelMapPack = new PixelMapPack();
  @State imageKnifeResource: Resource = $r('app.media.icon_loading')
  @State imageKnifeString: string = ''
  @State normalPixelMap: boolean = false;
  @State normalResource: boolean = true;
  previousData: ImageKnifeData = null;
  nowData: ImageKnifeData = null;
  build() {
    Stack() {
      //Image組件配置
      Image(this.normalPixelMap ? this.imageKnifePixelMapPack.pixelMap : (this.normalResource ? this.imageKnifeResource : this.imageKnifeString))
        .objectFit(this.imageKnifeOption.imageFit ? this.imageKnifeOption.imageFit : ImageFit.Fill)
        .visibility(this.imageVisible)
        .width(this.imageWidth)
        .height(this.imageHeight)
    }
  }
  //必要的用戶配置和回呼方法
  configNecessary(request: RequestOption){
    request.load(this.imageKnifeOption.loadSrc)
      .addListener((err, data) => {
        console.log('request.load callback')
        this.imageKnifeChangeSource(data)
        this.animateTo('image');
        return false;
      })
    if (this.imageKnifeOption.size) {
      request.setImageViewSize(this.imageKnifeOption.size)
    }
  }
  // imageknife 第一次啟動和資料重繪后重新發送請求
  imageKnifeExecute() {
    let request = new RequestOption();
    this.configNecessary(request);
    this.configCacheStrategy(request);
    this.configDisplay(request);
    ImageKnife.call(request);
  }
  //回傳資料Image渲染展示圖片
  imageKnifeSpecialFixed(data:ImageKnifeData) {
    if (data.isPixelMap()) {
      this.displayPixelMap(data);
    }
    else if (data.isString()) {
      this.displayString(data);
    } else if (data.isResource()) {
      this.displayResource(data);
    } else {
    }
  }
}


注:@State裝飾的變數是組件內部的狀態資料,當這些狀態資料被修改時,將會呼叫所在組件的build方法進行UI重繪,

 

三、ImageKnife實戰


通過上文的介紹,相信大家對ImageKnife組件有了深刻的了解,下面我們將創建一個ImageKnife_Test專案,為大家展示ArkUI開發框架中ImageKnife組件的使用,

 

通過將ImageKnife組件下載至專案中,然后根據ImageKnifeOption配置相關資訊,即可完成GIF圖片的加載, 

 

1. 創建專案


如圖8所示,在DevEco Studio中新建ImageKnife_Test專案,專案型別選擇Application,語言選擇eTS,點擊Finish完成創建, 

 

圖8 創建專案

 

2. 添加依賴


成功創建專案后,接下來就是將ImageKnife組件下載至專案中,

 

首先,我們需找到.npmrc 組態檔,并在檔案中添加 @ohos 的scope倉庫地址:@ohos:registry=https://repo.harmonyos.com/npm/,如圖9所示: 

 

圖9 添加 scope倉庫地址

 

配置好npm倉庫地址后,如圖10所示,在DevEco Studio的底部導航欄,點擊“Terminal”(快捷鍵Alt+F12),鍵入命令:npm install @ohos/imageknife并回車,此時ImageKnife組件會被自動下載至專案中,下載完成后工程根目錄下會生成node_modules/@ohos/imageknife目錄,

 

圖10 下載至專案

 

3. 撰寫邏輯代碼


ImageKnife組件成功下載至專案中后,接下來就是邏輯代碼撰寫,這里我們將為大家介紹兩種使用方式: 

 

方式一:首先初始化全域ImageKnife實體,然后在app.ets中呼叫ImageKnife.with()進行初始化,相關代碼如下: 

 

import {ImageKnife} from '@ohos/imageknife'
export default {
  data: {
    imageKnife: {} // ImageKnife
  },
  onCreate() {
    this.data.imageKnife = ImageKnife.with();
  },
  onDestroy() {
  },
}


然后在頁面index.ets中使用ImageKnife,相關代碼如下: 

 

@Entry
@Component
struct Index {
  build() {
  }
  // 頁面初始化完成,生命周期回呼函式中 進行呼叫ImageKnife
  aboutToAppear() {
    let requestOption = new RequestOption();
  requestOptin.load($r('app.media.IceCream'))
  .addListener((err,data) => {
      //加載成功/失敗回呼監聽
    })
    ...
  ImageKnife.call(requestOption)
  }
}
var ImageKnife;
var defaultTemp = globalThis.exports.default
if (defaultTemp != undefined) {
  ImageKnife = defaultTemp.data.imageKnife;
}


方式二:在index.ets中,直接使用ImageKnifeOption作為入參,并配合自定義組件ImageKnifeComponent使用,相關代碼如下: 

 

import {ImageKnifeOption} from '@ohos/imageknife'
@Entry
@Component
struct Index {
  @State imageKnifeOption1: ImageKnifeOption =
    {
      loadSrc: $r('app.media.gifSample'),
      size: { width: 300, height: 300 },
      placeholderSrc: $r('app.media.icon_loading'),
      errorholderSrc: $r('app.media.icon_failed')
    };
  build() {
    Scroll() {
      Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
        ImageKnifeComponent({ imageKnifeOption: $imageKnifeOption1 })
      }
    }
    .width('100%')
    .height('100%')
  }
}


以上就是本期全部內容,恭喜大家花幾分鐘時間識訓了一個實用的組件,希望廣大開發者能利用這個強大的開源組件開發出更多精美的應用,

 

 

搜索

復制

<iframe></iframe>

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/467109.html

標籤:其他

上一篇:Java在eclipse中運行并且會編譯,但不會在cmd上執行,但仍然在eclipse中運行。我怎樣才能讓它在cmd中執行?

下一篇:RecyclerView顯示串列

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more