欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

簡化Cocos和Native交互利器詳解

 更新時間:2022年12月09日 11:42:06   作者:我是黃大仙  
這篇文章主要為大家介紹了簡化Cocos和Native交互利器詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

背景

我們在使用 Cocos 和 Native 進(jìn)行交互的時候,發(fā)現(xiàn)體驗(yàn)并不是特別的友好。 如下所示,為我們項(xiàng)目當(dāng)中的一段代碼(代碼已脫敏),當(dāng)檢測到發(fā)生了 js 異常,我們需要通知 Native 端去做一些處理。

jsException: function (scence, msg, stack) {
    if (cc.sys.isNative && cc.sys.os === cc.sys.OS_ANDROID) {
        jsb.reflection.callStaticMethod(
            "xxx/xxx/xxx/xxx/xxx",
            "xxx",
            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
            scence, msg, stack
        );
    } else if (cc.sys.isNative && cc.sys.os === cc.sys.OS_IOS) {
        jsb.reflection.callStaticMethod(
            "xxx",
            "xxx:xxx:xxx:",
            scence, msg, stack
        );
    }
}

從代碼當(dāng)中我們可以看出有以下問題:

  • 方法調(diào)用非常麻煩,特別是 Android 端,需要明確的指出方法的路徑,方法名,參數(shù)類型,特別容易出錯;
  • 一旦 Native 端的方法發(fā)生變化,Cocos層必須要同步修改,否則就會出現(xiàn)異常,甚至有可能 crash;
  • 不方便回調(diào);

我們嘗試著用注解的思路來解決這些問題,從而設(shè)計(jì)并實(shí)現(xiàn)了 ABCBinding 。ABCBinding 能夠極大的簡化 Cocos和 Native 的交互,方便維護(hù)。

ABCBinding 的結(jié)構(gòu)設(shè)計(jì)

ABCBinding 的結(jié)構(gòu)如下圖所示:

ABCBinding 包含 Native 和 TS 兩個部分,Native 負(fù)責(zé)約束本地的方法,TS 負(fù)責(zé)對 Cocos 層提供調(diào)用 Native 方法的接口。 我們重新定義了一套 Cocos 和 Native 的交互模式:

  • 提供 Cocos 訪問的 Native 方法必須為 public static,且參數(shù)必須為 Transfer(Transfer 為 SDK 提供的接口,能夠在 Cocos 層和 Native 層傳遞數(shù)據(jù));
  • 方法必須使用 ABCBinder 注解修飾,并在注解內(nèi)傳入約定好的 tag,此 tag 用于唯一標(biāo)識這個方法;
  • 使用 SDK 提供的 callNativeMethod 方法,傳入約定好的 tag 調(diào)用 Native 方法。

例子: 如下所示,為調(diào)用 Native 方法去下載,我們只需要傳入約定好的 tag:downloadFile,并傳入?yún)?shù),便可以進(jìn)行下載了。 TS 層:

Binding.callNativeMethod('downloadFile', { url: 'https://xxx.jpeg' }
).then((result) => {
    this.label.string = `下載成功:path=${result.path}`;
}).catch((error) => {
    this.label.string = error.msg;
});

Native 層:

@ABCBinder("downloadFile")
public static void download(Transfer transfer){
    new Thread(new Runnable() {
        @Override
        public void run() {
            String url = transfer.get("url","");
            try{
                //下載中
	        ...
                //下載成功
                TransferData data = new TransferData();
                data.put("path","/xxx/xxx.jpg");
                transfer.onSuccess(data);
            }catch (Exception e){
                //失敗
                transfer.onFailure(e);
            }
        }
    }).start();
}

通過例子可以看到,使用 ABCBinding 能夠讓 Cocos 和 Native 的交互簡單很多,我們再也不用再傳入復(fù)雜的路徑和參數(shù)了,而且回調(diào)也變得很優(yōu)雅。接下來我們來看看 ABCBinding 是如何實(shí)現(xiàn)的。

具體實(shí)現(xiàn)

從上面的例子我們可以看出,ABCBinding 是通過 tag 來實(shí)現(xiàn) Cocos 和 Native 進(jìn)行交互的,那 SDK 是如何通過 tag 來找到對應(yīng)的方法呢?

通過 tag 找到 Native 方法

我們定義了編譯時注解 ABCBinder,

@Retention(RetentionPolicy.CLASS)//編譯時生效
@Target({ElementType.METHOD})//描述方法
public @interface ABCBinder {
    String value();
}

在編譯期間會生成一個類 ABCBindingProxy,成員變量 executors 包含了所有對應(yīng)的 tag 和方法。其中真正可執(zhí)行的方法被包裝在了 ExecutableMethod 接口當(dāng)中。

//以下為自動生成的代碼
private Map executors = new java.util.HashMap();

private ABCBindingProxy() {
  executors.put("test2",new ExecutableMethod() {
    @Override
    public void execute(Transfer t) {
      com.example.abcbinding.MainActivity.test2(t);
    }
  });
  executors.put("test1",new ExecutableMethod() {
    @Override
    public void execute(Transfer t) {
      com.example.abcbinding.MainActivity.test1(t);
    }
  });
}
public interface ExecutableMethod {
    void execute(Transfer t);
}

因此我們只需要通過 executors 和 tag 就可以找到了對應(yīng)的方法了,接著我們看看 TS 是如何與 Native 進(jìn)行交互的, 以下是 SDK 里面 TS 層的部分代碼,SDK 屏蔽了調(diào)用的具體細(xì)節(jié),將請求的參數(shù)轉(zhuǎn)變成為 json 字符串,并將相關(guān)的參數(shù)傳遞給 SDK 內(nèi)部的方法 execute,由 execute 將請求轉(zhuǎn)發(fā)給真正的方法。

public callNativeMethod(methodName: string, args ?: Record<string, string | number | boolean>): Promise < any > {
    ...
    if (cc.sys.isNative && cc.sys.os === cc.sys.OS_ANDROID) {
        let resultCode = jsb.reflection.callStaticMethod(
            'com/tencent/abckit/binding/ABCBinding', 
            'execute', 
            '(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I',
            methodName, 
            typeof args === 'object' ? JSON.stringify(args) : '', cbName);
        ...
    } else if (cc.sys.isNative && cc.sys.os === cc.sys.OS_IOS) {
        let retId = jsb.reflection.callStaticMethod(
            'ABCBinding', 
            'execute:methodName:args:callback:',
            methodName, 
            typeof args === 'object' ? JSON.stringify(args) : '', cbName);
        ...
    } else {
        let msg = 'no implemented on this platform';
        reject(msg);
    }
}

這樣,我們就解決了通過 tag 找到對應(yīng)方法的問題。但還有兩個問題需要解決: 如何約束 Native 方法?以及如何保證 tag 的唯一性?

約束 Native 方法

ABCBinding 規(guī)定,提供 Cocos 訪問的 Native 方法必須為 public static,參數(shù)必須為 Transfer,且 tag 必須要保持唯一性,那怎么來約束呢? 在代碼的編譯期間,我們會去檢查所有被 ABCBinder 修飾的方法,若發(fā)現(xiàn)這個方法并不符合我們的規(guī)范,則會直接報錯。 如下所示: 1.參數(shù)錯誤

@ABCBinder("test1")
public static void test1(Transfer transfer, int a) {
    Log.i("測試", "test()");
}

2.方法非 static

@ABCBinder("test2")
public void test2(Transfer transfer) {
    Log.i("測試", "test()");
}

3.方法非 public

@ABCBinder("test3")
protected static void test3(Transfer transfer) {
    Log.i("測試", "test()");
}

4.tag 重復(fù)

@ABCBinder("helloworld")
public static void test1(Transfer transfer) {
    Log.i("測試", "test()");
}

@ABCBinder("helloworld")
public static void test2(Transfer transfer) {
    Log.i("測試", "test()");
}

優(yōu)雅的回調(diào)

SDK 會在編譯期間自動生成 callJs 方法,所有的回調(diào)都是通過 callJs 方法實(shí)現(xiàn)。Native 方法只需要調(diào)用 Transfer 所提供的回調(diào)接口,便可以輕松的將結(jié)果回調(diào)給 Cocos。由于 callJs 代碼是自動生成,所以 SDK 不需要直接依賴 Cocos 庫,只需要業(yè)務(wù)方依賴即可。

//以下為自動生成的代碼
public void callJs(final String globalMethod, final TransferData params) {
  org.cocos2dx.lib.Cocos2dxHelper.runOnGLThread(new Runnable() {
    @Override
    public void run() {
      String command = String.format("window && window.%s && window.%s(%s);", 
	  globalMethod,globalMethod, params.parseJson());;
      org.cocos2dx.lib.Cocos2dxJavascriptJavaBridge.evalString(command);;
    }
  });
}

ABCBinding 提供了onProcess,onSuccess 和 onFailed 回調(diào)方法, 以下為 downloadFile 接口的的回調(diào)示例: TS 層:

Binding.withOptions({
    //回調(diào)onProcess
    onProgress: (progress) => {
        let current = progress.current;
        this.label.string = `progress:${current}`;
    }
}).callNativeMethod(
    'downloadFile',
    { url: 'https://xxxx.jpg' }
).then((result) => {
    //回調(diào)onSuccess
    this.label.string = `下載成功:path=${result.path}`;
}).catch((error) => {
    //回調(diào)onFailed
    if (error) {
        this.label.string = error.msg;
    }
});

Native 層:

@ABCBinder("downloadFile")
public static void download(Transfer transfer){
    new Thread(new Runnable() {
        @Override
        public void run() {
            String url = transfer.get("url","");
            try{
              	//模擬下載過程
                for(int i =0;i<100;i++) {
                     transfer.onProgress("current", i);
                }
	       //下載成功
                TransferData data = new TransferData();
                data.put("path","/xxx/xxx.jpg");
                transfer.onSuccess(data);
            }catch (Exception e){
                //失敗
                transfer.onFailure(e);
            }
        }
    }).start();
}

其他 feature

抹平系統(tǒng)差異

使用 ABCBinding 無須再判斷當(dāng)前系統(tǒng)是 Android 還是 IOS ,只需對應(yīng) Native 方法的 tag 保持一致即可。

Binding.callNativeMethod('isLowDevice').then(({isLowDevice}) => {
  console.log(isLowDevice);
})

無需關(guān)心線程切換

Native 方法使用 Transfer 回調(diào)時,ABCBinding 會自動切換到 Cocos 線程執(zhí)行,無需業(yè)務(wù)方關(guān)心。

@ABCBinding("getHardwareInfo")
public static void getHardwareInfo(Transfer transfer) {
    TransferData data = new TransferData();
    data.put("brand", Build.BRAND);
    data.put("model", Build.MODEL);
    data.put("OsVersion", Build.VERSION.RELEASE);
    data.put("SdkVersion", Build.VERSION.SDK);
    transfer.onSuccess(data);
}

支持超時

ABCBinding 支持設(shè)置超時,其中超時的時間單位為秒,如下所示,超時會回調(diào)到 catch 方法當(dāng)中。

Binding.withOptions({
    timeout: 120,
    onProgress: (progress) => {
        let current = progress.current;
        this.label.string = `progress:${current}`;
    }
}).callNativeMethod(
    'downloadFile',
    { url: 'https://xxxx.jpg' }
).then((result) => {
    this.label.string = `下載成功:path=${result.path}`;
}).catch((error) => {
    if (error.code == ERROR_CODE_TIMEOUT) {
         console.log("超時");
    }
});

彩蛋:在熱更新當(dāng)中的應(yīng)用

我們在使用 Cocos 熱更新服務(wù)的過程中發(fā)現(xiàn),怎么確定 Cocos 熱更新包能夠發(fā)布到哪個 App 版本,是個難題。Cocos 熱更新包能不能在這個 App 版本上正確運(yùn)行,跟兩個因素有關(guān),Cocos 版本和 Native 接口。

Cocos 版本 如果 App 和熱更包的 Cocos 版本不一致,那么很有可能這個熱更包無法在 App 上運(yùn)行,除非官方做了一些兼容處理。不過這個因素可控,Cocos 的版本不會頻繁的升級,而且我們知道 Cocos 版本和 App 版本的對應(yīng)關(guān)系。

Native 接口 如果熱更包調(diào)用了某個 Native 的接口,但是這個接口在有些版本上不存在,那該熱更包就無法在這個版本的 App 上運(yùn)行。 在我們的業(yè)務(wù)場景當(dāng)中,Cocos 版本不會頻繁變更,但是每個版本的 Native 代碼可能會相差較大,人工來核對每個版本的 Native 接口變更是一件極為費(fèi)時費(fèi)力的事情。 那么 ABCBinding 能幫助我們做什么呢?

讓熱更包兼容所有版本的 App

首先我們?nèi)コ?Cocos 版本的因素,因?yàn)檫@個因素可控,且業(yè)務(wù)方無法解決。 ABCBinding 知道本地有哪些接口可用,所以當(dāng) Cocos 調(diào)用了一個不存在的接口時,我們會返回一個特殊的 code,這樣熱更包只需要在內(nèi)部做兼容處理就可以了。 如下所示:

Binding.callNativeMethod('downloadFile', { url: 'https://xxx.jpeg' }
).then((result) => {
     //處理邏輯
}).catch((error) => {
    if(error.code == ERROR_CODE_METHOD_NOT_DEFINED){
        console.log("未找到該方法");
    }
});

元素綁定

既然熱更新跟這兩個元素有關(guān),我們就可以通過這兩個元素,讓 App 和熱更包進(jìn)行匹配,如果能夠匹配,那么這個熱更包就可以下發(fā)到這個版本的 App 上。 Cocos 版本:我們在打包的時候就可以確定; Native 接口:在打包的過程中,ABCBinding 可以將當(dāng)前所支持的接口,按照約定的方式生成一個元素。 例如:本地的接口有 test1,test2,test3 我們可以將接口按照指定的方式排序拼接取 md5 值,生成第二個元素。 這樣當(dāng) App 和熱更新包的兩個元素能夠匹配時,就能夠下發(fā)了。

以上就是簡化Cocos和Native交互利器詳解的詳細(xì)內(nèi)容,更多關(guān)于Cocos Native交互簡化的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • react?native?reanimated實(shí)現(xiàn)動畫示例詳解

    react?native?reanimated實(shí)現(xiàn)動畫示例詳解

    這篇文章主要為大家介紹了react?native?reanimated實(shí)現(xiàn)動畫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • react最流行的生態(tài)替代antdpro搭建輕量級后臺管理

    react最流行的生態(tài)替代antdpro搭建輕量級后臺管理

    這篇文章主要為大家介紹了react最流行的生態(tài)替代antdpro搭建輕量級后臺管理示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 詳解React??App.js?文件的結(jié)構(gòu)和作用

    詳解React??App.js?文件的結(jié)構(gòu)和作用

    在React應(yīng)用中,App.js文件通常是項(xiàng)目的根組件文件,它負(fù)責(zé)組織和渲染其他組件,是應(yīng)用的核心部分,本文將詳細(xì)介紹App.js文件的結(jié)構(gòu)、作用和最佳實(shí)踐,感興趣的朋友跟隨小編一起看看吧
    2024-08-08
  • 如何去除富文本中的html標(biāo)簽及vue、react、微信小程序中的過濾器

    如何去除富文本中的html標(biāo)簽及vue、react、微信小程序中的過濾器

    這篇文章主要介紹了如何去除富文本中的html標(biāo)簽及vue、react、微信小程序中的過濾器,在vue及react中經(jīng)常會遇到,今天通過實(shí)例代碼給大家講解,需要的朋友可以參考下
    2018-11-11
  • React四級菜單的實(shí)現(xiàn)

    React四級菜單的實(shí)現(xiàn)

    本文主要介紹了React四級菜單的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • 使用React實(shí)現(xiàn)內(nèi)容滑動組件效果

    使用React實(shí)現(xiàn)內(nèi)容滑動組件效果

    這篇文章主要介紹了使用React實(shí)現(xiàn)一個內(nèi)容滑動組件效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-05-05
  • React?中使用?Redux?的?4?種寫法小結(jié)

    React?中使用?Redux?的?4?種寫法小結(jié)

    這篇文章主要介紹了在?React?中使用?Redux?的?4?種寫法,Redux 一般來說并不是必須的,只有在項(xiàng)目比較復(fù)雜的時候,比如多個分散在不同地方的組件使用同一個狀態(tài),本文就React使用?Redux的相關(guān)知識給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2022-06-06
  • React路由鑒權(quán)的實(shí)現(xiàn)方法

    React路由鑒權(quán)的實(shí)現(xiàn)方法

    這篇文章主要介紹了React路由鑒權(quán)的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • React Native 搭建開發(fā)環(huán)境的方法步驟

    React Native 搭建開發(fā)環(huán)境的方法步驟

    本篇文章主要介紹了React Native 搭建開發(fā)環(huán)境的方法步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • 一個基于react的圖片裁剪組件示例

    一個基于react的圖片裁剪組件示例

    本篇文章主要介紹了一個基于react的圖片裁剪組件示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04

最新評論