Harmony 發(fā)展
鴻蒙的發(fā)展其實有一段時間了事哭,并且隨著鴻蒙的發(fā)展一直都有兩方面的爭議,一方認為鴻蒙是基于Android開發(fā)的操作系統(tǒng)怔匣,質(zhì)疑鴻蒙只是把外表改了的Android昔脯;另一方則認為鴻蒙是華為自主研發(fā)的操作系統(tǒng)笑陈,在智能手機和智能平板應用上采用的與Android兼容快集。
隨著今年8月份 HarmoneyOs4的發(fā)布贡羔,并表示后續(xù)的Harmony NEXT將不基于Android,這一系列的爭論看起來已經(jīng)結(jié)束了个初。華為官方宣稱不兼容Android后將壓縮優(yōu)化40%的代碼乖寒,應該指的就是HarmonyOs中兼容Android的那部分AOSP的代碼。
因為如果要兼容Android的話勃黍,這部分AOSP的代碼是肯定會要存在的宵统,站在華為的立場也可以理解,比較系統(tǒng)的推廣離不開生態(tài)覆获,唯一的辦法,就是在安卓的基礎上瓢省,先進行逐步的替換修改弄息,保持對安卓的兼容性,降低APP提供商的開發(fā)成本勤婚,讓系統(tǒng)先面世摹量。然后系統(tǒng)面世后,逐步擴大用戶數(shù)量,提升知名度缨称,擴大影響力凝果。有了一定的影響力和基礎,才能去和更多的APP提供商和開發(fā)者合作睦尽,讓他們針對我的系統(tǒng)器净,去開發(fā)APP,構建生態(tài)当凡。
照目前來看山害,鴻蒙已經(jīng)是走到了構建生態(tài)的這一步來了。
我們可以看下鴻蒙開發(fā)者的官網(wǎng),其實已經(jīng)很完善了沿量。從IDE浪慌,到相關的課程文檔,到Codelabs都是配套齊全的朴则,完全夠我們開發(fā)者上手和入門了权纤,并且由于是中文文檔,確實體驗比谷歌的機器翻譯的文檔要易懂不少??乌妒。
Harmony 開發(fā)
- 嚴格來講妖碉,Harmony 開發(fā)應該指的是兩部分,應用開發(fā) 和 設備開發(fā)芥被。設備開發(fā)指的是比如芯片/模組/開發(fā)板之類的硬件與鴻蒙的兼容或通訊欧宜,場景是智能家居一類的,畢竟OpenHarmony初衷是萬物互聯(lián)嘛拴魄。 而我們這里講的是應用開發(fā)冗茸。
IDE 和 開發(fā)語言
首先開發(fā)用的IDE是HUAWEI DevEco Studio,是基于IDEA開發(fā)的匹中,所以和Android Studio比起來夏漱,不能說毫無關系,只能說是一模一樣顶捷。這對安卓開發(fā)者來說還是很友好的挂绰。
然后開發(fā)語言是arkts
,它是基于TypeScript(簡稱TS)基礎上,對TS的動態(tài)類型特性施加更嚴格的約束服赎,引入靜態(tài)類型葵蒂。并且借助ArkUI的框架,提供了聲明式UI重虑、狀態(tài)管理的能力践付,用起來還是比較簡潔的。
開發(fā)體驗
鴻蒙原生的開發(fā)缺厉,官方給出了兩套開發(fā)模型永高,一套是基于Java或Js的FA模型隧土,對應的版本是API 8也就是Harmony3.0及以前,這種就是xxAbility,被吐槽看起來很像Android的Activity的開發(fā)方式命爬。
不過隨著鴻蒙的發(fā)展曹傀,Java已經(jīng)不再受支持了,現(xiàn)在官方推薦的就是剛才提到的基于ArkTs的Stage模型饲宛,提出了AbilityStage皆愉、WindowStage等類作為應用組件和Window窗口的“舞臺”,兩個模型的差異官網(wǎng)也給出了詳細的說明落萎,我這里依然使用的官方主推的Stage模型開發(fā)亥啦。
ArkUi開發(fā)體驗
一個簡單的計數(shù)器Demo,借助arkTs的注解(ts里面叫裝飾器)完成對狀態(tài)的管理,ui開發(fā)用的是聲明式的語法练链,熟悉Flutter或者React的同學應該很親切翔脱。整個寫法看起來還是很簡潔的。
@Entry
@Component
struct ParentComponent {
@State number: number = 0
build() {
Stack() {
Text(`${this.number}`)
.fontSize(26)
.position({ x: '50%', y: '50%' })
Button() {
Image($r('app.media.ic_public_add'))
.width(50)
.height(50)
}
.width(60)
.height(60)
.position({ x: '80%', y: 600 })
.type(ButtonType.Circle)
.backgroundColor(0xFFFFFF)
.onClick(() => {
this.number++
})
}
}
}
TypeScript
簡單介紹一下TypeScript媒鼓,TypeScript是由微軟開發(fā)的一款開源的編程語言届吁。 其官方對它的定義是Typed JavaScript at Any Scale.添加了類型系統(tǒng)的 JavaScript,適用于任何規(guī)模的項目绿鸣。
首先Ts完全兼容Js,Typed的意思是在JavaScript的基礎上疚沐,增加了靜態(tài)類型的檢查。
動態(tài)/靜態(tài)類型
我們知道語言按照「類型檢查的時機」來分類潮模,可以分為動態(tài)類型和靜態(tài)類型亮蛔。動態(tài)類型是指在運行時才會進行類型檢查,優(yōu)點是寫代碼很靈活方便擎厢,不用去寫非常多的類型定義究流,缺點就是代碼質(zhì)量參差不齊,維護成本高动遭,比如有些錯誤在編譯期不會報錯芬探,而在運行時會報錯。這樣的缺點對于一個大型項目來說是很致命的厘惦。
而TypeScript 是靜態(tài)類型的語言偷仿,所以能在編譯階段就會進行類型檢查,有問題就會報錯宵蕉,為開發(fā)者提供了便利酝静。
強/弱類型
強類型是指變量定義后,不允許改變變量的數(shù)據(jù)類型国裳,除非進行強制類型轉(zhuǎn)換形入。相反,弱類型就是指變量的值其類型是寬泛的缝左,可以被賦值多種類型的值。
舉例來說這段代碼在js中是可以正常運行的:
let a = 1;
a = 'a';
按理來說,ts是完全兼容javaScript的渺杉,既然完全兼容蛇数,那么照網(wǎng)上的一些說法,ts應該也是屬于弱類型的語言是越。
但是上面這段代碼放在ts中耳舅,編譯器就會提示 Type 'string' is not assignable to type 'number'.(不能將類型“string”分配給類型“number”)
這個其實是ESLint 提供的代碼檢查功能,我試了一下,因為這段代碼雖然飄紅倚评,但是運行起來是沒問題的浦徊。
也就是說ts雖然是弱類型的語言,但在開發(fā)的體驗上天梧,是能避免寫出弱類型的代碼的盔性。
總之,ts就是對Js加了類型的檢查呢岗,所以ts比之于js會更適合大型項目的開發(fā)與維護冕香。而鴻蒙的ArkTs也是完全兼容Ts語法的。
語言發(fā)展
上面說的一些對比可以看出javaScript的一些不足和對大型項目開發(fā)的限制后豫,這里也順便聊聊TypeScript的發(fā)展故事悉尾。
2011 年 9 月,網(wǎng)絡上出現(xiàn)了一封標題為"Future of JavaScript"的谷歌內(nèi)部郵件,郵件中表明,由于 Javascript 語言發(fā)展緩慢,谷歌內(nèi)部正在開發(fā)一門比 JavaScript 更好的 web 語言。
這門新語言的目標是實現(xiàn) JavaScript 所能實現(xiàn)的一切功能挫酿。它的主要目標是"保持 JavaScript 的動態(tài)特性,但要有更好的性能构眯,配置文件,并能適應大型項目的工具"早龟。它還可以交叉編譯成 JavaScript惫霸。這種語言作為技術預覽版向更廣泛的世界發(fā)布,并命名為 Dart。
對拄衰,Dart其實和Ts的初衷一樣它褪,都是為了成為更好的Javascript,而且兩門語言的面世時間其實差不多翘悉,dart面世于2011年茫打,ts面世于2012年,緊隨其后妖混;dart是由Google團隊開發(fā)老赤,ts的背后團隊是微軟,兩者在一段時間內(nèi)是競爭關系制市。
后來dart在與typescript競爭中‘誰才是更好的js’中輸給了ts(這里的“競爭”并不是指語言和技術層面上的競爭抬旺,也有可能商業(yè)和市場層面上的競爭)反正最終的結(jié)果是Ts如今作為更好的js,已經(jīng)在各大前端框架上普及祥楣,react开财,vue和Angular都在積極的支持與使用ts汉柒。
而dart在沉靜了一段時間后則借助Flutter和跨平臺的興起,再次出現(xiàn)在公眾面前责鳍。
所以碾褂,單從語言本身來說,三者是有很多的相似之處的历葛。比如js和dart都是單線程的正塌,js可以通過瀏覽器的多線程去完成長時間耗時任務,dart可以通過平臺通道恤溶。所以我們來看看ts在鴻蒙上是怎么執(zhí)行長時間耗時任務的乓诽。
多線程支持
并發(fā)和多線程
異步并發(fā)是指異步代碼在執(zhí)行到一定程度后會被暫停,以便在未來某個時間點繼續(xù)執(zhí)行咒程,這種情況下鸠天,同一時間只有一段代碼在執(zhí)行。如:aysnc/promise
多線程并發(fā)允許在同一時間段內(nèi)同時執(zhí)行多段代碼孵坚。在主線程繼續(xù)響應用戶操作和更新UI的同時粮宛,后臺也能執(zhí)行耗時操作,從而避免應用出現(xiàn)卡頓卖宠。
HarmonyOs對多線程的開發(fā)提供了兩種方式巍杈,TaskPool和Worker,可以官網(wǎng)看對比
示例
import Prompt from '@system.prompt'
import taskpool from '@ohos.taskpool';
import worker from '@ohos.worker';
@Entry
@Component
struct ParentComponent {
@State number: number = 0
build() {
Column({ space: 20 }) {
LoadingProgress().width(100).height(100)
Button("setTimeout執(zhí)行耗時任務")
.onClick(() => {
longTaskWithTimeOut()
})
Button("taskPool執(zhí)行耗時任務")
.onClick(() => {
doWithTaskPool()
})
Button("worker執(zhí)行耗時任務")
.onClick(() => {
doWithTaskPool()
})
}.width("100%").height("100%")
}
}
function longTask(): string {
console.log("開始長任務");
const startTime = Date.now();
while (Date.now() - startTime < 1000) {
}
console.log(`執(zhí)行完畢長任務扛伍,耗時${(startTime - Date.now())}ms`);
return "ok"
}
async function longTaskWithTimeOut() {
let result: string = await new Promise<string>((success, error) => {
setTimeout(() => {
success(longTask());
}, 0);
})
Prompt.showToast({ message: `result is ${result}` })
}
@Concurrent
function task() {
const startTime = Date.now();
while (Date.now() - startTime < 1000) {
}
return "ok"
}
/**
* 適合單個完整的任務
*/
function doWithTaskPool() {
const tmpTask = new taskpool.Task(task)
taskpool.execute(tmpTask).then(result => {
Prompt.showToast({ message: `Result : ${result}` })
})
// const promise: Promise<unknown> = taskpool.execute(tmpTask)
// const data = await promise
}
function doWithWorker() {
const tmpWorker = new worker.ThreadWorker(`entry/src/main/ets/workers/DemoWorker.ts`);
tmpWorker.onmessage = result => {
Prompt.showToast({ message: `Result : ${result}` })
}
// 向Worker子線程發(fā)送Get消息
tmpWorker.postMessage({ data: "data" })
// tmpWorker.terminate()
}taskpool.execute(tmpTask)
// const data = await promise
}
// worker.ets
import worker, { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope } from '@ohos.worker';
var workerPort: ThreadWorkerGlobalScope = worker.workerPort;
workerPort.onmessage = function (e: MessageEvents) {
const startTime = Date.now();
while (Date.now() - startTime < 1000) {
}
workerPort.postMessage("ok")
}