0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

HarmonyOS開發(fā)實(shí)戰(zhàn):【親子拼圖游戲】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-04-16 17:00 ? 次閱讀

概述

本篇Codelab是基于TS擴(kuò)展的聲明式開發(fā)范式編程語言編寫的一個分布式益智拼圖游戲,可以兩臺設(shè)備同時開啟一局拼圖游戲,每次點(diǎn)擊九宮格內(nèi)的圖片,都會同步更新兩臺設(shè)備的圖片位置。效果圖如下:

說明: 本示例涉及使用系統(tǒng)接口,需要手動替換Full SDK才能編譯通過。

搭建OpenHarmony環(huán)境

完成本篇Codelab我們首先要完成開發(fā)環(huán)境的搭建,本示例以Hi3516DV300開發(fā)板為例,參照以下步驟進(jìn)行:

  1. [獲取OpenHarmony系統(tǒng)版本]):標(biāo)準(zhǔn)系統(tǒng)解決方案(二進(jìn)制)。
    以3.0版本為例:
  2. 搭建燒錄環(huán)境。
    1. [完成DevEco Device Tool的安裝]
    2. [完成Hi3516開發(fā)板的燒錄]
    3. 鴻蒙開發(fā)指導(dǎo):[qr23.cn/AKFP8k]
  3. 搭建開發(fā)環(huán)境。
    1. 開始前請參考[工具準(zhǔn)備],完成DevEco Studio的安裝和開發(fā)環(huán)境配置。
    2. 開發(fā)環(huán)境配置完成后,請參考[使用工程向?qū)創(chuàng)建工程(模板選擇“Empty Ability”),選擇JS或者eTS語言開發(fā)。
    3. 工程創(chuàng)建完成后,選擇使用[真機(jī)進(jìn)行調(diào)測]。
      2.鴻蒙HarmonyOS與OpenHarmony文檔籽料mau123789是v直接拿

搜狗高速瀏覽器截圖20240326151450.png

分布式組網(wǎng)

本章節(jié)以系統(tǒng)自帶的音樂播放器為例(具體以實(shí)際的應(yīng)用為準(zhǔn)),介紹如何完成兩臺設(shè)備的分布式組網(wǎng)。

  1. 硬件準(zhǔn)備:準(zhǔn)備兩臺燒錄相同的版本系統(tǒng)的Hi3516DV300開發(fā)板A、B。

  2. 開發(fā)板A、B連接同一個WiFi網(wǎng)絡(luò)。
    打開設(shè)置-->WLAN-->點(diǎn)擊右側(cè)WiFi開關(guān)-->點(diǎn)擊目標(biāo)WiFi并輸入密碼。

  3. 將設(shè)備A,B設(shè)置為互相信任的設(shè)備。

    • 找到系統(tǒng)應(yīng)用“音樂”。

    • 設(shè)備A打開音樂,點(diǎn)擊左下角流轉(zhuǎn)按鈕,彈出列表框,在列表中會展示遠(yuǎn)端設(shè)備的id。
    • 選擇遠(yuǎn)端設(shè)備B的id,另一臺開發(fā)板(設(shè)備B)會彈出驗(yàn)證的選項框。
    • 設(shè)備B點(diǎn)擊允許,設(shè)備B將會彈出隨機(jī)PIN碼,將設(shè)備B的PIN碼輸入到設(shè)備A的PIN碼填入框中。


    配網(wǎng)完畢。

代碼結(jié)構(gòu)解讀

本篇Codelab只對核心代碼進(jìn)行講解,首先來介紹下整個工程的代碼結(jié)構(gòu):

  • MainAbility:存放應(yīng)用主頁面。
    • pages/index.ets:應(yīng)用主頁面。
  • model:存放獲取組網(wǎng)內(nèi)的設(shè)備列表相關(guān)文件。
    • RemoteDeviceModel.ets:獲取組網(wǎng)內(nèi)的設(shè)備列表。
  • ServiceAbility:存放ServiceAbility相關(guān)文件。
    • service.ts:service服務(wù),創(chuàng)建一個ServiceAbility,用于跨設(shè)備連接后通訊。
  • resources :存放工程使用到的資源文件。
    • resources/rawfile:存放工程中使用的圖片資源文件。
  • config.json:配置文件。

實(shí)現(xiàn)頁面布局和樣式

在本章節(jié)中,您將學(xué)會如何制作一個簡單的拼圖游戲。

  1. 實(shí)現(xiàn)主頁面布局和樣式。
    • 在MainAbility/pages/index.ets 主界面文件中添加入口組件PictureGame。PictureGame組件頁面布局代碼如下:

      // 入口組件
      @Entry
      @Component
      struct PictureGame {
        @Provide imageIndexForPosition: number[] = []
        @Provide pictureList: string[]= []
        build() {
          Column() {
            Text("益智拼圖游戲").fontSize(40).margin({ top: 30, bottom: 30 })
            PictureGrid()
            Row() {
              Button("重新開始").fontSize(20).margin({ right: 10 }).onClick(() = > {
                ...
              })
              Button("親子協(xié)同").fontSize(20).margin({ left: 10 }).onClick(()= >{
                ...
              })
            }.margin(30)
            Image($rawfile('picture.jpg')).width(300).height(300)
      
          }
          .width('100%')
          .height('100%')
        }
      }
      
    • 給PictureGame組件添加九宮格拼圖子組件PictureGrid。PictureGrid九宮格拼圖組件主要是由[Grid組件]、[GridItem組件]和[Image組件]構(gòu)成,頁面布局代碼如下:

      // 九宮格拼圖組件
      @Component
      struct PictureGrid {
        private gridRowTemplate: string = ''
        @Consume imageIndexForPosition : number[]
        @Consume pictureList: string[]
        private heightValue: number
      
        aboutToAppear() {
          var rows = Math.round(this.pictureList.length / 3);
          this.gridRowTemplate = '1fr '.repeat(rows);
          this.heightValue = rows * 101 ;
        }
      
        build() {
          Column() {
            Grid() {
              ForEach(this.pictureList.map((item,index)= >{return {i:index,data:item};}),(item,index) = > {
                GridItem() {
                  Image($rawfile(this.pictureList[item.i]))
                    .width(100)
                    .height(100)
                    .onClick(() = > {
                     ...
                    })
                }
              }, (item: string) = > item.toString())
            }
            .rowsTemplate(this.gridRowTemplate)
            .columnsTemplate('1fr 1fr 1fr')
            .columnsGap(1)
            .rowsGap(1)
            .height(this.heightValue)
            .width(303)
          }
        }
      }
      

      在入口組件的生命周期函數(shù)aboutToAppear()中調(diào)用onRandom()方法,初始化imageIndexForPosition數(shù)組。如果Ability是被其他設(shè)備拉起的,在aboutToAppear()中調(diào)用featureAbility.getWant(),可通過want中的參數(shù)重新初始化imageIndexForPosition數(shù)組和pictureList數(shù)組,入口組件的生命周期函數(shù)aboutToAppear()代碼如下:

      async aboutToAppear() {
        let self =this;
        this.onRandom();
        // 當(dāng)被拉起時,通過want傳遞的參數(shù)同步對端界面UI
        await featureAbility.getWant((error, want) = > {
          var status = want.parameters;
          if(want.parameters.pictureList){
            self.pictureList = JSON.parse(status.pictureList)
            self.imageIndexForPosition = status.imageIndexForPosition;
            // 遠(yuǎn)端被拉起后,連接對端的service
            if(want.parameters.remoteDeviceId) {
              let remoteDeviceId = want.parameters.remoteDeviceId
              onConnectRemoteService(remoteDeviceId)
            }
          }
        });
      }
      
  2. 給"重新開始"按鈕添加點(diǎn)擊事件。
    點(diǎn)擊"重新開始"按鈕,調(diào)用onRandom()方法,打亂圖片現(xiàn)階段排列順序,在onRandom()調(diào)用setupRandomPosition()方法,初始化imageIndexForPosition數(shù)組,onRandom()和setupRandomPosition()代碼如下:
    onRandom() {
      this.setupRandomPosition();
      this.pictureList = []
      this.imageIndexForPosition.forEach(value = > {
        if (value == 9) {
          this.pictureList.push("--")
        } else {
          this.pictureList.push(`picture_0` + value + `.png`)
        }
      });
    }
    // 初始化imageIndexForPosition數(shù)組
    setupRandomPosition() {
      let list1 = [5, 4, 3, 9, 1, 8, 6, 7, 2];
      let list2 = [3, 1, 6, 7, 9, 8, 4, 2, 5];
      let list3 = [4, 8, 3, 5, 2, 7, 9, 1, 6];
      let list4 = [4, 3, 5, 2, 8, 7, 6, 1, 9];
      let lists = [list1, list2, list3, list4];
      this.imageIndexForPosition = lists[Math.floor(Math.random() * 4)];
    }
    
  3. 給九宮格內(nèi)的每張圖片添加點(diǎn)擊事件。
    點(diǎn)擊九宮格內(nèi)的圖片,調(diào)用onchange()方法,每一次點(diǎn)擊后,需要調(diào)用onFinish()方法校驗(yàn)當(dāng)前imageIndexForPosition 中的元素是否是從小到大排列。其中onChange()和onFinish()方法代碼如下
    onChange(index) {
      let self = this;
      // 相鄰位置數(shù)組
      let menu = {
        "1": [2, 4],
        "2": [1, 3, 5],
        "3": [2, 6],
        "4": [1, 5, 7],
        "5": [2, 4, 6, 8],
        "6": [3, 5, 9],
        "7": [4, 8],
        "8": [5, 7, 9],
        "9": [6, 8]
      }
      // 被點(diǎn)擊的圖片位置
      let click_num = index + 1;
      // 空白圖片位置
      let no_see_num = self.imageIndexForPosition.indexOf(9) + 1;
      // 獲取點(diǎn)擊后能夠移動的圖片位置
      let arr = menu[no_see_num];
      // 判斷arr是否包含點(diǎn)擊的圖片
      if(arr.length==2){
        if (!(arr[0]==click_num||arr[1]==click_num)) {
    
        } else {
          let temp = self.imageIndexForPosition[no_see_num - 1];
          self.imageIndexForPosition[no_see_num - 1] = self.imageIndexForPosition[click_num - 1];
          self.imageIndexForPosition[click_num - 1] = temp;
    
          self.pictureList = [];
          self.imageIndexForPosition.forEach(value = > {
            if (value == 9) {
              self.pictureList.push("--")
            } else {
              self.pictureList.push(`picture_0` + value + `.png`)
            }
          });
        }
      }else if(arr.length==3){
        if (!(arr[0]==click_num||arr[1]==click_num||arr[2]==click_num)) {
    
        } else {
          let temp = self.imageIndexForPosition[no_see_num - 1];
          self.imageIndexForPosition[no_see_num - 1] = self.imageIndexForPosition[click_num - 1];
          self.imageIndexForPosition[click_num - 1] = temp;
    
          self.pictureList = [];
          self.imageIndexForPosition.forEach(value = > {
            if (value == 9) {
              self.pictureList.push("--")
            } else {
              self.pictureList.push(`picture_0` + value + `.png`)
            }
          });
        }
      }else if(arr.length==4){
        if (!(arr[0]==click_num||arr[1]==click_num||arr[2]==click_num||arr[3]==click_num)) {
    
        } else {
          let temp = self.imageIndexForPosition[no_see_num - 1];
          self.imageIndexForPosition[no_see_num - 1] = self.imageIndexForPosition[click_num - 1];
          self.imageIndexForPosition[click_num - 1] = temp;
    
          self.pictureList = [];
          self.imageIndexForPosition.forEach(value = > {
            if (value == 9) {
              self.pictureList.push("--")
            } else {
              self.pictureList.push(`picture_0` + value + `.png`)
            }
          });
        }
      }
      // 發(fā)送消息到遠(yuǎn)端Service服務(wù)
      sendMessageToRemoteService(JSON.stringify(self.imageIndexForPosition));
      // 判斷是否完成拼接
      self.onFinish();
    }
    
    onFinish() {
      let finalList = [1, 2, 3, 4, 5, 6, 7, 8, 9];
      if (this.equarList(this.imageIndexForPosition, finalList)) {
        this.pictureList = [];
        this.imageIndexForPosition.forEach(value = > {
          this.pictureList.push("picture_0" + value + ".png")
        });
        prompt.showToast({
          message: "success"
        });
        // 完成拼接后斷開Service連接
        onDisconnectService();
      }
    }
    

拉起遠(yuǎn)端FA,并連接遠(yuǎn)端Service服務(wù)

在本章節(jié)中,您將學(xué)會如何拉起在同一組網(wǎng)內(nèi)的設(shè)備上的FA,創(chuàng)建并連接遠(yuǎn)端Service服務(wù)。

  1. 調(diào)用featureAbility.startAbility()方法,拉起遠(yuǎn)端FA,并同步界面UI。
    點(diǎn)擊"親子協(xié)同"按鈕,調(diào)用RegisterDeviceListCallback()發(fā)現(xiàn)設(shè)備列表,并彈出設(shè)備列表選擇框CustomDialogExample,選擇設(shè)備后拉起遠(yuǎn)端FA。CustomDialogExample()代碼如下:

    // 設(shè)備列表彈出框
    @CustomDialog
    struct CustomDialogExample {
      @State editFlag: boolean = false
      @Consume imageIndexForPosition : number[]
      @Consume pictureList: string[]
      controller: CustomDialogController
      cancel: () = > void
      confirm: () = > void
      build() {
        Column() {
          List({ space: 10, initialIndex: 0 }) {
            ForEach(DeviceIdList, (item) = > {
              ListItem() {
                Row() {
                  Text(item)
                    .width('87%').height(50).fontSize(10)
                    .textAlign(TextAlign.Center).borderRadius(10).backgroundColor(0xFFFFFF)
                    .onClick(() = > {
                      onStartRemoteAbility(item,this.imageIndexForPosition,this.pictureList);
                      this.controller.close();
                    })
                  Radio({value:item})
                    .onChange((isChecked) = > {
                      onStartRemoteAbility(item,this.imageIndexForPosition,this.pictureList);
                      this.controller.close();
                    }).checked(false)
                }
              }.editable(this.editFlag)
            }, item = > item)
          }
        }.width('100%').height(200).backgroundColor(0xDCDCDC).padding({ top: 5 })
      }
    }
    

    點(diǎn)擊Text組件或者Radio組件都會調(diào)用onStartRemoteAbility()方法拉起遠(yuǎn)端FA,onStartRemoteAbility()代碼如下:

    function onStartRemoteAbility(deviceId,imageIndexForPosition,pictureList: string[]) {
      AuthDevice(deviceId);
      let numDevices = remoteDeviceModel.deviceList.length;
      if (numDevices === 0) {
        prompt.showToast({
          message: "onStartRemoteAbility no device found"
        });
        return;
      }
    
      var params = {
        imageIndexForPosition: JSON.stringify(imageIndexForPosition),
        pictureList : JSON.stringify(pictureList),
        remoteDeviceId : localDeviceId
      }
      var wantValue = {
        bundleName: 'com.huawei.cookbook',
        abilityName: 'com.example.openharmonypicturegame.MainAbility',
        deviceId: deviceId,
        parameters: params
      };
      featureAbility.startAbility({
        want: wantValue
      }).then((data) = > {
        // 拉起遠(yuǎn)端后,連接遠(yuǎn)端service
        onConnectRemoteService(deviceId)
      });
    }
    

    創(chuàng)建ServiceAbility,步驟如下圖所示:

  2. 調(diào)用featureAbility.connectAbility方法,連接遠(yuǎn)端Service服務(wù),連接成功后返會remote對象。
    在featureAbility.startAbility()成功的回調(diào)中調(diào)用onConnectRemoteService()方法,onConnectRemoteService()方法代碼如下:

    // 連接遠(yuǎn)端Service
    async function onConnectRemoteService(deviceId) {
      // 連接成功的回調(diào)
      async function onConnectCallback(element, remote) {
         mRemote = remote;
      }
      // Service異常死亡的回調(diào)
      function onDisconnectCallback(element) {
      }
      // 連接失敗的回調(diào)
      function onFailedCallback(code) {
        prompt.showToast({
          message: "onConnectRemoteService onFailed: " + code
        });
      }
      let numDevices = remoteDeviceModel.deviceList.length;
      if (numDevices === 0) {
        prompt.showToast({
          message: "onConnectRemoteService no device found"
        });
        return;
      }
      connectedAbility = await featureAbility.connectAbility(
        {
          deviceId: deviceId,
          bundleName: "com.huawei.cookbook",
          abilityName: "com.example.openharmonypicturegame.ServiceAbility",
        },
        {
          onConnect: onConnectCallback,
          onDisconnect: onDisconnectCallback,
          onFailed: onFailedCallback,
        },
      );
    }
    

    在配置文件config.json需要設(shè)置ServiceAbility的屬性visible為true,代碼如下:

    "abilities": [
          ...
          {
            "visible": true,
            "srcPath": "ServiceAbility",
            "name": ".ServiceAbility",
            "icon": "$media:icon",
            "srcLanguage": "ets",
            "description": "$string:description_serviceability",
            "type": "service"
          }
    ],
    

    同時,Service側(cè)也需要在onConnect()時返回IRemoteObject,從而定義與Service進(jìn)行通信的接口。onConnect()需要返回一個IRemoteObject對象,OpenHarmony提供了IRemoteObject的默認(rèn)實(shí)現(xiàn),通過繼承rpc.RemoteObject來創(chuàng)建自定義的實(shí)現(xiàn)類。Service側(cè)把自身的實(shí)例返回給調(diào)用側(cè)的代碼如下:

    import rpc from "@ohos.rpc";
    import commonEvent from '@ohos.commonEvent';
    class FirstServiceAbilityStub extends rpc.RemoteObject{
        constructor(des) {
            if (typeof des === 'string') {
                super(des);
            } else {
                return null;
            }
        }
        onRemoteRequest(code, data, reply, option) {
            if (code === 1) {
                let arr = data.readIntArray();
                reply.writeInt(100);
                // 發(fā)布公共事件相關(guān)流程
    	    ...
    
    
            } else {
            }
            return true;
        }
    }
    
    export default {
        // 創(chuàng)建Service的時候調(diào)用,用于Service的初始化
        onStart() {
        },
        // 在Service銷毀時調(diào)用。Service應(yīng)通過實(shí)現(xiàn)此方法來清理任何資源,如關(guān)閉線程、注冊的偵聽器等。
        onStop() {
        },
        // 在Ability和Service連接時調(diào)用,該方法返回IRemoteObject對象,開發(fā)者可以在該回調(diào)函數(shù)中生成對應(yīng)Service的IPC通信通道
        onConnect(want) {
            try {
                let value = JSON.stringify(want);
            } catch(error) {
            }
            return new FirstServiceAbilityStub("[pictureGame] first ts service stub");
        },
        // 在Ability與綁定的Service斷開連接時調(diào)用
        onDisconnect(want) {
            let value = JSON.stringify(want);
        },
        // 在Service創(chuàng)建完成之后調(diào)用,該方法在客戶端每次啟動該Service時都會調(diào)用
        onCommand(want, startId) {
            let value = JSON.stringify(want);
        }
    };
    

RPC跨設(shè)備通訊

在本章節(jié)中,您將學(xué)會在成功連接遠(yuǎn)端Service服務(wù)的前提下,如何利用RPC進(jìn)行跨設(shè)備通訊。

  1. 成功連接遠(yuǎn)端Service服務(wù)的前提下,點(diǎn)擊"重新開始"按鈕或者九宮格內(nèi)的圖片,都會完成一次跨設(shè)備通訊,假如在設(shè)備A端點(diǎn)擊"重新開始"按鈕,消息的傳遞是由設(shè)備A端的FA傳遞到設(shè)備B的Service服務(wù),發(fā)送消息的方法sendMessageToRemoteService()代碼如下:
    // 連接成功后發(fā)送消息
    async function sendMessageToRemoteService(imageIndexForPosition) {
      if (mRemote == null) {
        prompt.showToast({
          message: "mRemote is null"
        });
        return;
      }
      let option = new rpc.MessageOption();
      let data = new rpc.MessageParcel();
      let reply = new rpc.MessageParcel();
      data.writeIntArray(JSON.parse(imageIndexForPosition));
      await mRemote.sendRequest(1, data, reply, option);
      let msg = reply.readInt();
    }
    
  2. 在B端的Service接收消息,當(dāng)A端成功連接B端Service服務(wù)后,在A端會返回一個remote對象,當(dāng)A端remote對象調(diào)用sendRequest()方法后,在B端的Service中的onRemoteRequest()方法中會接收到發(fā)送的消息,其中繼承rpc.RemoteObject的類和onRemoteRequest()方法代碼如下:
    class FirstServiceAbilityStub extends rpc.RemoteObject{
        constructor(des) {
            if (typeof des === 'string') {
                super(des);
            } else {
                return null;
            }
        }
    
        onRemoteRequest(code, data, reply, option) {
            if (code === 1) {
                // 從data中接收數(shù)據(jù)
                let arr = data.readIntArray();
                // 回復(fù)接收成功標(biāo)識
                reply.writeInt(100);
                // 發(fā)布公共事件相關(guān)流程
               ...
    
            } else {
            }
            return true;
        }
    }
    

Service服務(wù)發(fā)布公共事件

當(dāng)Service服務(wù)接收到消息后,在onRemoteRequest()發(fā)布公共事件,代碼如下:

onRemoteRequest(code, data, reply, option) {
    if (code === 1) {
	// 從data中接收數(shù)據(jù)
	let arr = data.readIntArray();
	// 回復(fù)接收成功標(biāo)識
	reply.writeInt(100);
	// 公共事件相關(guān)信息
	var params ={
	    imageIndexForPosition: arr
	}
	var options = {
            // 公共事件的初始代碼
	    code: 1,
            // 公共事件的初始數(shù)據(jù)			
	    data: 'init data',、
            // 有序公共事件 	        
	    isOrdered: true, 	
	    bundleName: 'com.huawei.cookbook',
	    parameters: params

        }
	// 發(fā)布公共事件回調(diào)
	function PublishCallBack() {
	}
	// 發(fā)布公共事件
	commonEvent.publish("publish_moveImage", options, PublishCallBack);

	} else {
	}
	return true;
 }

在接收到消息后,把接收到的圖片位置數(shù)組放入params中,然后發(fā)布名稱為"publish_moveImage"的有序公共事件。

FA訂閱公共事件

在本章節(jié)中,您將學(xué)會如何通過CommonEvent訂閱公共事件。在九宮格組件PictureGrid的生命周期函數(shù)aboutToAppear()中,調(diào)用訂閱公共事件方法subscribeEvent(),用來訂閱"publish_moveImage"公共事件,subscribeEvent()代碼如下:

subscribeEvent(){
    let self = this;
    // 用于保存創(chuàng)建成功的訂閱者對象,后續(xù)使用其完成訂閱及退訂的動作
    var subscriber; 
    // 訂閱者信息
    var subscribeInfo = {
      events: ["publish_moveImage"],
      priority: 100

    };

    // 設(shè)置有序公共事件的結(jié)果代碼回調(diào)
    function SetCodeCallBack(err) {
    }
    // 設(shè)置有序公共事件的結(jié)果數(shù)據(jù)回調(diào)
    function SetDataCallBack(err) {
    }
    // 完成本次有序公共事件處理回調(diào)
    function FinishCommonEventCallBack(err) {
    }
    // 訂閱公共事件回調(diào)
    function SubscribeCallBack(err, data) {
      let msgData = data.data;
      let code = data.code;
      // 設(shè)置有序公共事件的結(jié)果代碼
      subscriber.setCode(code, SetCodeCallBack);
      // 設(shè)置有序公共事件的結(jié)果數(shù)據(jù)
      subscriber.setData(msgData, SetDataCallBack);
      // 完成本次有序公共事件處理
      subscriber.finishCommonEvent(FinishCommonEventCallBack)
      // 處理接收到的數(shù)據(jù)data
      self.imageIndexForPosition = data.parameters.imageIndexForPosition;
      self.pictureList = [];
      self.imageIndexForPosition.forEach(value = > {
        if (value == 9) {
          self.pictureList.push("--")
        } else {
          self.pictureList.push(`picture_0` + value + `.png`)
        }
      });

      self.onFinish();
    }

    // 創(chuàng)建訂閱者回調(diào)
    function CreateSubscriberCallBack(err, data) {
      subscriber = data;
      // 訂閱公共事件
      commonEvent.subscribe(subscriber, SubscribeCallBack);
    }

    // 創(chuàng)建訂閱者
    commonEvent.createSubscriber(subscribeInfo, CreateSubscriberCallBack);
 }

在FA中訂閱到Service服務(wù)發(fā)布的"publish_moveImage"事件后,在SubscribeCallBack()回調(diào)中重新賦值imageIndexForPosition數(shù)組與pictureList數(shù)組,從而同步更新界面UI。

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 鴻蒙
    +關(guān)注

    關(guān)注

    56

    文章

    2267

    瀏覽量

    42493
  • HarmonyOS
    +關(guān)注

    關(guān)注

    79

    文章

    1946

    瀏覽量

    29740
  • OpenHarmony
    +關(guān)注

    關(guān)注

    25

    文章

    3548

    瀏覽量

    15743
收藏 人收藏

    評論

    相關(guān)推薦

    拼圖游戲之新鳥求教老鳥

    本帖最后由 yl383576734 于 2012-4-11 16:47 編輯 如何在這個拼圖游戲中,加入統(tǒng)計按鍵次數(shù)和類似排行榜一樣的東西,記錄每一次完成拼圖游戲的按鍵次數(shù),求給位大神幫忙啊
    發(fā)表于 04-11 16:42

    拼圖游戲

    本帖最后由 eehome 于 2013-1-5 09:57 編輯 拼圖
    發(fā)表于 05-24 22:23

    鍵盤拼圖游戲

    在做鍵盤拼圖游戲時,為什么運(yùn)行時點(diǎn)擊按鈕圖片沒有反應(yīng)??求各位大神指導(dǎo)。。。
    發(fā)表于 04-06 10:25

    求一份基于labview的拼圖游戲設(shè)計與論文。。。。

    求一份基于labview的拼圖游戲設(shè)計與論文。。。。
    發(fā)表于 04-13 19:28

    一個基于Labview的簡易拼圖游戲,各位看官可以看看!順便問下為什么我不能進(jìn)行驗(yàn)證郵箱任務(wù)?

    ` 本帖最后由 幻世紀(jì) 于 2017-1-11 00:58 編輯 一個基于Labview的簡易拼圖游戲,各位看官可以看看!順便問下注冊完后,為什么我不能像他們一樣進(jìn)行再次驗(yàn)證郵箱任務(wù)?`
    發(fā)表于 01-11 00:53

    基于屬性節(jié)點(diǎn)調(diào)用的拼圖游戲

    基于屬性節(jié)點(diǎn)調(diào)用的、拼圖游戲
    發(fā)表于 04-07 23:08

    HarmonyOS教程—分布式親子早教系統(tǒng)

    1. 項目介紹遠(yuǎn)程教育,多屏協(xié)同是智慧教育的一個重要場景。本篇Codelab通過一個親子早教系統(tǒng),完成了分布式早教算數(shù)題和分布式拼圖游戲兩個綜合案例,旨在幫助開發(fā)者快速了解HarmonyOS
    發(fā)表于 09-14 11:06

    基于STM32設(shè)計的拼圖游戲的設(shè)計資料分享

    /download/xiaolong1126626497/20706318二、運(yùn)行效果三、功能介紹因?yàn)榇a原來是在2.8寸屏上設(shè)計的,但是2.8寸屏摔碎了,現(xiàn)在手上只有塊3.5寸的LCD屏。就把代碼移植到3.5寸屏上顯示了,目前運(yùn)行的效果可以看上面的效果圖。拼圖游戲在...
    發(fā)表于 12-03 08:20

    拼圖游戲(java)

    拼圖游戲(java)   java編寫的一款簡單的拼圖游戲,可以下載到手機(jī)上玩。..rar
    發(fā)表于 04-09 15:18 ?37次下載

    labview拼圖游戲程序

    此程序是基于狀態(tài)機(jī)編程的labview拼圖游戲,共分為五個狀態(tài),其中puzzle.vi為主程序
    發(fā)表于 10-29 15:00 ?106次下載

    Delphi教程_奇妙的拼圖游戲

    Delphi教程奇妙的拼圖游戲,很好的Delphi資料,快來下載學(xué)習(xí)吧。
    發(fā)表于 03-16 14:56 ?5次下載

    LabVIEW拼圖游戲的仿真與設(shè)計課程詳細(xì)說明

    熟悉LabVIEW開發(fā)環(huán)境,掌握基于LabVIEW的虛擬儀器原理、設(shè)計方法和實(shí)現(xiàn)技巧,運(yùn)用專業(yè)課程中的基本理論和實(shí)踐知識,采用LabVIEW開發(fā)工具,實(shí)現(xiàn)拼圖游戲設(shè)計和仿真。要求最終實(shí)現(xiàn)模擬一個
    發(fā)表于 04-23 08:00 ?29次下載
    LabVIEW<b class='flag-5'>拼圖游戲</b>的仿真與設(shè)計課程詳細(xì)說明

    如何用C語言實(shí)現(xiàn)拼圖游戲項目

    ? 這篇文章主要為大家詳細(xì)介紹了 C語言實(shí)現(xiàn)——《拼圖游戲項目》 ,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下! ? 游戲介紹: 對剛開始接觸拼圖的玩家而言,所謂
    的頭像 發(fā)表于 11-11 14:13 ?1761次閱讀

    基于STM32設(shè)計的拼圖游戲詳解

    拼圖游戲在小時候還是經(jīng)常玩,玩法也比較簡單,這里就使用STM32設(shè)計一個拼圖游戲分享出來一起學(xué)習(xí)。 目前游戲是通過開發(fā)板上4按鍵進(jìn)行
    的頭像 發(fā)表于 02-28 13:45 ?2982次閱讀
    基于STM32設(shè)計的<b class='flag-5'>拼圖</b>小<b class='flag-5'>游戲</b>詳解

    C語言+easyX帶你實(shí)現(xiàn):數(shù)字拼圖游戲

    這是一個簡易的拼圖游戲,一共有 15 個數(shù)字方塊,將其一行行的排列為 1~15 即可完成。游戲會記錄下完成拼圖的時間。我想說的是,很多時候,精彩的游戲不一定非要用圖片。將
    的頭像 發(fā)表于 02-26 10:01 ?919次閱讀