提前申請(qǐng)和準(zhǔn)備要要用的證書(shū)

嵐山網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)建站!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)建站自2013年創(chuàng)立以來(lái)到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專(zhuān)注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)建站。
用HBuilderX打正式包。
1)要在manifest.json里面配置App圖標(biāo)和啟動(dòng)圖片
2)App圖標(biāo)尺寸:png 格式圖片 256*256
啟動(dòng)圖片尺寸:png 格式圖片 480762 7201242 1080*1882
3. app上架材料梳理:
一般看個(gè)人要求,在騰訊、華為、小米各個(gè)平臺(tái)上線(xiàn)。
每個(gè)平臺(tái)都要注冊(cè)開(kāi)發(fā)者賬號(hào),用企業(yè)信息注冊(cè),注意開(kāi)發(fā)者賬號(hào)公司和軟著要一致,否則華為、騰訊會(huì)讓你重新按軟著上的公司名稱(chēng)注冊(cè)開(kāi)發(fā)者賬號(hào)。小米要提供一個(gè)代理授權(quán)書(shū)。
1)共同提交的材料:
1.公司名稱(chēng)
2.公司營(yíng)業(yè)執(zhí)照、其中百度需要營(yíng)業(yè)執(zhí)照復(fù)印件并且在文字的地方加蓋公章。
3.企業(yè)法人身份證照片(正反兩面),其中百度另外要求上傳手持身份證照片(正反兩面)。
4.企業(yè)對(duì)公賬號(hào),其中華為和小米打錢(qián)驗(yàn)證,利用金額進(jìn)行驗(yàn)證。
5.企業(yè)地址。
2)?提交應(yīng)用審核資料:
1.軟著,jpg,png,pdf,3種格式。
2.企業(yè)營(yíng)業(yè)執(zhí)照,pg,png,pdf,種格式。
3.圖標(biāo),尺寸不一致。216216 jpg 512512 jpg
4.應(yīng)用內(nèi)截圖,多截幾張,最后用測(cè)試賬號(hào)截圖。
5.應(yīng)用簡(jiǎn)介和應(yīng)用描述。
9.icp備案截圖。
7.如果軟著公司和開(kāi)發(fā)者賬號(hào)不一致,需要提供代理授權(quán)書(shū),簽字蓋章。
8.隱私政策網(wǎng)址。
上架成功后需要在各個(gè)商城自行下載。
點(diǎn)擊 “協(xié)議、稅務(wù)和銀行業(yè)務(wù)”
內(nèi)購(gòu)用的是付費(fèi)應(yīng)用程序,先簽署《付費(fèi)應(yīng)用程序協(xié)議》,同意后狀態(tài)變更為“用戶(hù)信息待處理”,等待審核。
狀態(tài)更改完畢后,點(diǎn)擊“開(kāi)始設(shè)置稅務(wù)、銀行業(yè)務(wù)和聯(lián)系信息”。
(1)添加銀行賬戶(hù),按照要求填寫(xiě)相關(guān)內(nèi)容即可。
(2)選擇報(bào)稅表,并填寫(xiě)。所有與 Apple 有商業(yè)合作者必選都是美國(guó),若有其他需求,可以多選。
繼續(xù)填寫(xiě),首先認(rèn)證公司基本信息,選擇所有人類(lèi)型,確認(rèn)無(wú)誤后認(rèn)證條款處打?qū)?/p>
Part I 部分,繼續(xù)核對(duì)公司相關(guān)信息,選填內(nèi)容可不填。
Part III 部分,簽署稅務(wù)條約,設(shè)置利益限制條款的種類(lèi),選填內(nèi)容可不填。此部分如果需要可勾選上下圖勾選框,不需要可不勾選,我們這個(gè)項(xiàng)目沒(méi)有用到part III 部分,所以沒(méi)有勾選。
Part XXX 部分,確認(rèn)之前填寫(xiě)的信息,勾選完畢后,提交
(3)填寫(xiě)聯(lián)系信息,共5個(gè)。高級(jí)管理、財(cái)務(wù)、技術(shù)、法務(wù)、營(yíng)銷(xiāo)。只需要提供5個(gè)人的基本信息即可。
只可使用一次的產(chǎn)品,使用之后即失效,必須再次購(gòu)買(mǎi)。
示例: 釣魚(yú) App 中的魚(yú)食。
只需購(gòu)買(mǎi)一次,不會(huì)過(guò)期或隨著使用而減少的產(chǎn)品。
示例: 游戲 App 的賽道。
允許用戶(hù)在固定時(shí)間段內(nèi)購(gòu)買(mǎi)動(dòng)態(tài)內(nèi)容的產(chǎn)品。除非用戶(hù)選擇取消,否則此類(lèi)訂閱會(huì)自動(dòng)續(xù)期。
示例: 每月訂閱提供流媒體服務(wù)的 App。
允許用戶(hù)購(gòu)買(mǎi)有時(shí)限性服務(wù)的產(chǎn)品。此 App 內(nèi)購(gòu)買(mǎi)項(xiàng)目的內(nèi)容可以是靜態(tài)的。此類(lèi)訂閱不會(huì)自動(dòng)續(xù)期。
示例: 為期一年的已歸檔文章目錄訂閱。
App 內(nèi)購(gòu)買(mǎi)項(xiàng)目的截屏,即所售項(xiàng)目的示意圖。例如,如果 App 內(nèi)購(gòu)買(mǎi)項(xiàng)目是一本圖書(shū),您可以提交圖書(shū)的截屏。您也可以提交購(gòu)買(mǎi)頁(yè)的截屏。該截屏僅用于 Apple 審核,不會(huì)在 App Store 中顯示。
截屏要求如下:
iOS 至少需要 640 x 920 像素
Apple tvOS 需要 1920 x 1080 像素
macOS 需要 1280 x 800 像素
App 審核圖像上傳后,可以替換,但無(wú)法移除。當(dāng)您的 App 內(nèi)購(gòu)買(mǎi)項(xiàng)目處于審核中時(shí),您無(wú)法更新截屏。
沙箱賬號(hào)是不能直接在A(yíng)pp Store進(jìn)行登錄的,只能在點(diǎn)擊了購(gòu)買(mǎi)商品之后,在彈出的登錄框進(jìn)行登錄 。
驗(yàn)證是否已登錄沙箱測(cè)試賬號(hào):
設(shè)置--iTunes Store與App Store,頁(yè)面拉到最底部,會(huì)看到沙箱賬戶(hù)項(xiàng)會(huì)列出你已登錄的沙箱測(cè)試賬號(hào)!
操作方法一:打開(kāi)App Store應(yīng)用首頁(yè)滑到最下方--選中AppleID--注銷(xiāo)
操作方法二:設(shè)置--iTunes Store與App Store--選中AppleID--注銷(xiāo)
checks if the client can make payments(檢測(cè)App是否能支付)
getAvailablePurchases
Get all non-consumed purchases 獲取未消費(fèi)的商品
打印信息查詢(xún);
原因:
沒(méi)有先執(zhí)行g(shù)etProducts,直接執(zhí)行requestPurchase方法,要先拉取商品列表,再執(zhí)行購(gòu)買(mǎi)操作.
問(wèn)題描述;
1.漏單必須要處理,玩家花RMB購(gòu)買(mǎi)的東西卻丟失了,是絕對(duì)不能容忍的。所謂的漏單就是玩家已經(jīng)正常付費(fèi),卻沒(méi)有拿到該拿的道具。
解決:只要購(gòu)買(mǎi)成功,便將購(gòu)買(mǎi)記錄(receipt等賬單信息)保存下來(lái),然后將賬單信息傳送給我們游戲服務(wù)器,游戲服務(wù)器獲得賬單后,和蘋(píng)果服務(wù)器驗(yàn)證,賬單有效的話(huà),回饋給游戲服務(wù)器處理,游戲服務(wù)器處理后,返回給游戲客戶(hù)端處理,處理完畢,將本地保存的購(gòu)買(mǎi)記錄刪除。
官方文檔:向蘋(píng)果校驗(yàn)支付憑證
21000 App Store無(wú)法讀取你提供的JSON數(shù)據(jù)
21002 收據(jù)數(shù)據(jù)不符合格式
21003 收據(jù)無(wú)法被驗(yàn)證
21004 你提供的共享密鑰和賬戶(hù)的共享密鑰不一致
21005 收據(jù)服務(wù)器當(dāng)前不可用
21006 收據(jù)是有效的,但訂閱服務(wù)已經(jīng)過(guò)期。當(dāng)收到這個(gè)信息時(shí),解碼后的收據(jù)信息也包含在返回內(nèi)容中
21007 收據(jù)信息是測(cè)試用(sandbox),但卻被發(fā)送到產(chǎn)品環(huán)境中驗(yàn)證 【請(qǐng)求sandbox校驗(yàn)支付憑證】
21008 收據(jù)信息是產(chǎn)品環(huán)境中使用,但卻被發(fā)送到測(cè)試環(huán)境中驗(yàn)證
消耗類(lèi)型: 例如:金幣、道具等。
非續(xù)訂訂閱: non-renewable subscription 例如:VIP
您的首個(gè) App 內(nèi)購(gòu)買(mǎi)項(xiàng)目必須以新的 App 版本提交。請(qǐng)創(chuàng)建您的 App 內(nèi)購(gòu)買(mǎi)項(xiàng)目,然后前往 App 的“App Store”頁(yè),從“App 內(nèi)購(gòu)買(mǎi)項(xiàng)目”中進(jìn)行選擇,點(diǎn)按“提交”。 了解更多
在上傳二進(jìn)制文件并提交首個(gè) App 內(nèi)購(gòu)買(mǎi)項(xiàng)目以供審核后,您可以使用下表提交其他 App 內(nèi)購(gòu)買(mǎi)項(xiàng)目。
唐巧-iOS應(yīng)用內(nèi)付費(fèi)(IAP)開(kāi)發(fā)步驟列表
未完~待續(xù)
當(dāng)使用內(nèi)購(gòu)購(gòu)買(mǎi)過(guò)商品之后沒(méi)有把這個(gè)交易關(guān)閉,所以再次去購(gòu)買(mǎi)商品后就會(huì)調(diào)用以前已經(jīng)購(gòu)買(mǎi)成功的交易去購(gòu)買(mǎi)因?yàn)橐呀?jīng)購(gòu)買(mǎi)過(guò),才會(huì)有這個(gè)提示
原因:添加內(nèi)購(gòu)項(xiàng)目時(shí),信息填寫(xiě)不完整,app審核圖像未上傳
處理方法:上傳app審核圖片( 合適的尺寸 ),點(diǎn)擊提交,狀態(tài)改為正在準(zhǔn)備審核中。
這個(gè)是內(nèi)購(gòu)選擇類(lèi)型不匹配原因?qū)е隆?/p>
購(gòu)買(mǎi)成功之后,Apple會(huì)返回以下四個(gè)數(shù)據(jù)給應(yīng)用
Reference
Review the updated Paid Applications Schedule.
游客身份解決方案:即不登錄也要能購(gòu)買(mǎi)
1)服務(wù)器端做一個(gè)蘋(píng)果審核機(jī)制,審核期間游客身份可以進(jìn)行一切行為,一旦審核通過(guò),修改服務(wù)端即可達(dá)到強(qiáng)制用戶(hù)登錄進(jìn)行內(nèi)購(gòu)買(mǎi)的目的(這個(gè)有點(diǎn)。。。)
2)游客可以進(jìn)行內(nèi)購(gòu)買(mǎi),購(gòu)買(mǎi)時(shí)以設(shè)備UUID為準(zhǔn),生成一個(gè)游客賬號(hào),將購(gòu)買(mǎi)信息保存在服務(wù)器和本地,當(dāng)用戶(hù)登錄正式賬戶(hù)后判斷此設(shè)備是否進(jìn)行過(guò)內(nèi)購(gòu),有的話(huà)提示用戶(hù)將游客身份購(gòu)買(mǎi)的權(quán)益與現(xiàn)有賬號(hào)綁定,如果綁定,游客權(quán)益則遷移到正式賬戶(hù),如果不遷移,則游客身份和正是賬戶(hù)是兩個(gè)獨(dú)立賬戶(hù),正式賬戶(hù)不享有游客身份的權(quán)益(我用的這個(gè))
內(nèi)購(gòu)游客模式解決方案
iOS內(nèi)購(gòu)規(guī)則
注:亮度調(diào)節(jié)和音量調(diào)節(jié)gif無(wú)法體現(xiàn),功能是ok的,其次默認(rèn)Icon鎖的close和open實(shí)在難以分辨。
環(huán)境:Flutter 2.8.1 channel stable ;Dart 2.15.1
需要音頻播放器的看這里: Flutter音樂(lè)播放器
重點(diǎn)說(shuō)下這個(gè)工具類(lèi),因?yàn)橐曨l播放,涉及到狀態(tài)改變有很多,筆者剛開(kāi)始選擇使用 InheritedWidget 來(lái)在眾多的widget之間共享數(shù)據(jù)。但是總感覺(jué)這樣有點(diǎn)繁瑣,且不很優(yōu)雅!
這里非廣告,如果是使用 GetX 就很簡(jiǎn)單了,筆者也使用了 GetX 進(jìn)行封裝了,一瀉千里的趕腳!,但是筆者還是那句話(huà):剛開(kāi)始接觸Flutter的開(kāi)發(fā)者不是很建議使用 GetX ,可以先熟悉下Flutter狀態(tài)管理的基礎(chǔ)原理再行使用。而且為了盡量簡(jiǎn)潔,還是不引入其他的第三方了。
我們選擇對(duì)第三方插件進(jìn)行封裝的目的不外乎這幾個(gè):
于是筆者就寫(xiě)了一個(gè)工具類(lèi) VideoPlayerUtils ,專(zhuān)門(mén)且只用來(lái)處理播放器的所有業(yè)務(wù)。包括暫停、播放、跳轉(zhuǎn)、調(diào)節(jié)音量、調(diào)節(jié)亮度、切換視頻等操作。在所有的widget中不會(huì)引用關(guān)于 video_player 或其他第三方插件的任何信息, VideoPlayerUtils 負(fù)責(zé)widget與播放器之間的所有操作交互。后續(xù)優(yōu)化迭代或更換播放器插件時(shí),只需針對(duì)這個(gè)工具類(lèi)進(jìn)行修改,對(duì)所有widget不會(huì)有任何的影響,大大的解耦合了。
其中 VideoPlayerState :
提供以上的公共屬性,可以通過(guò) VideoPlayerUtils 來(lái)獲取對(duì)應(yīng)的值,使用 get 只讀,使外界不會(huì)誤修改這些屬性,以保證數(shù)值的安全性。開(kāi)發(fā)者可根據(jù)自身需要自行添加屬性。
提供以上方法來(lái)處理播放器的所有業(yè)務(wù)。同樣的開(kāi)發(fā)者可根據(jù)自身需要自行添加或修改。
重點(diǎn)說(shuō)下這個(gè)方法,是整個(gè)業(yè)務(wù)的核心方法,控制視頻的播放或暫停。開(kāi)發(fā)者只要遇到播放或暫停是均可調(diào)用此方法,具體是播放或暫停,內(nèi)部根據(jù)傳入的 url 自行判斷,開(kāi)發(fā)者不需要關(guān)心。
切換新視頻也是使用此方法,傳入的 url 與上次不一致,自動(dòng)切換新視頻。筆者可根據(jù) statusListener 來(lái)監(jiān)聽(tīng)播放狀態(tài)的改變,以此處理自身邏輯。
這個(gè)也需要提下,視頻播放器在播放新視頻時(shí)會(huì)異步初始化,一般我們的操作是在 initState() 初始化,成功后再 setState() 。這里筆者遇到一個(gè)讓人蛋疼的問(wèn)題:
我們看 video_player 的使用:
VideoPlayer(controller) :widget中已經(jīng)持有了controller。本來(lái)筆者封裝的目的就是為了讓widget與controller的之間解耦合。但此時(shí)的筆者。。。。
放棄不是不可能放棄的,這輩子都不會(huì)放棄的!
于是筆者取了巧,寫(xiě)了一個(gè)初始化監(jiān)聽(tīng)器 initializedListener ,包換2個(gè)參數(shù): bool,Widget ,初始化是否成功;其中widget為初始化成功返回需要展示的播放器UI,失敗默認(rèn)返回 const SizedBox() 。
到這里就可以簡(jiǎn)單使用了:
沒(méi)看錯(cuò),視頻播放就是這么簡(jiǎn)單。
如果有更多的業(yè)務(wù)功能,筆者也按照自己的需求寫(xiě)了一套,同樣的開(kāi)發(fā)者可根據(jù)自身需要自行添加或修改。
VideoPlayerGestures 主要是處理手勢(shì)的,比如快進(jìn)、快退等跳轉(zhuǎn)播放;左側(cè)上下滑動(dòng)調(diào)節(jié)亮度;右側(cè)上下滑動(dòng)調(diào)節(jié)音量;單擊是否開(kāi)啟沉浸式播放,所有widget的隱藏與顯示;雙擊播放、暫停等。
哦,還有 PercentageWidget 也放到這個(gè)文件下了,就是這玩意:
因?yàn)轱@示的百分比與手勢(shì)相關(guān),隨著手勢(shì)移動(dòng)而更新。開(kāi)發(fā)者可自行處理。
筆者處出于簡(jiǎn)單考慮,就按照整個(gè)UI的位置命名了。瞅一眼就知道是啥玩意。
同樣的開(kāi)發(fā)者可根據(jù)自身需要自行添加或修改。
就是這玩意:
同樣的開(kāi)發(fā)者可根據(jù)自身需要自行添加或修改。話(huà)說(shuō)這個(gè)鎖的 Icon 的open和close是真的難分辨!
就是這玩意:
同樣的開(kāi)發(fā)者可根據(jù)自身需要自行添加或修改。
這玩意是自定義的,別問(wèn),問(wèn)就是跟產(chǎn)品干一架落了下風(fēng)
主要就是自定義這玩意:
同樣的開(kāi)發(fā)者可根據(jù)自身需要自定義。
注:這里沒(méi)有添加緩沖的進(jìn)度,開(kāi)發(fā)可查看 video_player 中的源碼 VideoProgressIndicator ,按業(yè)務(wù)自行定義。
這玩意就是整合以上的widget,再考慮下全屏的安全區(qū)域,沒(méi)啥東西。開(kāi)發(fā)者可自行處理!
具體的實(shí)現(xiàn)監(jiān)聽(tīng)器的思路, 看這里 。
自此一個(gè)漂亮的Flutter視頻播放器就已經(jīng)結(jié)束了。如果您覺(jué)得對(duì)您有些許幫助的話(huà),歡迎 Star !
本文面向 Flutter 初學(xué)者,旨在用易懂的方式帶大家入門(mén)。除了 Flutter 代碼,還會(huì)介紹到語(yǔ)法、原理、特性等基礎(chǔ)知識(shí)。相信本文能幫助你學(xué)習(xí)和理解 Flutter。
我們先看一下目前的一些跨平臺(tái)方案,從前端渲染的角度來(lái)分類(lèi)的話(huà),大致可以分為以下幾種方案。
WebView 渲染
這種方案就很好理解,現(xiàn)在很多項(xiàng)目都會(huì)嵌入 H5 的頁(yè)面。就是用 JavaScript 等前端技術(shù)進(jìn)行開(kāi)發(fā),在客戶(hù)端上用 WebView 來(lái)進(jìn)行渲染。微信小程序目前使用的就是這種方案。
它的優(yōu)點(diǎn)很明顯,使用成熟的前端技術(shù)進(jìn)行開(kāi)發(fā),學(xué)習(xí)成本低,開(kāi)發(fā)效率高,并且支持動(dòng)態(tài)發(fā)布代碼。
但缺點(diǎn)也很明顯,在性能體驗(yàn)上,和原生還是存在較大差距的。
原生控件渲染
既然 WebView 的性能不夠好,于是就有了使用原生控件進(jìn)行渲染的方案。這種方案,同樣也是使用 JavaScript 開(kāi)發(fā),區(qū)別是它最終是調(diào)用原生控件進(jìn)行渲染的。這種方案的代表是 Facebook 的 React Native。
由于使用原生控件進(jìn)行渲染,性能體驗(yàn)也會(huì)更接近原生。但也只是更接近,和原生還是有差距的,因?yàn)樗枰l繁的進(jìn)行 JavaScript 和原生之間的通信,這個(gè)通信效率是比較低的。
另外,由于需要適配各個(gè)平臺(tái)的控件,那就有可能出現(xiàn),系統(tǒng)控件更新了,而框架本身還沒(méi)有更新,由此產(chǎn)生了一些問(wèn)題。換句話(huà)說(shuō),這種方案是受到原生控件限制的。
繪圖引擎渲染
接下來(lái)就是主角了。
在前端,如果完全不使用原生控件,我們可以通過(guò)系統(tǒng)的繪圖 API 繪制出一個(gè)用戶(hù)界面。從這個(gè)角度出發(fā),可以在各個(gè)平臺(tái)使用一個(gè)統(tǒng)一接口的繪圖引擎來(lái)進(jìn)行界面繪制,這個(gè)引擎最終調(diào)用的是系統(tǒng)的 API 繪制的。這樣的話(huà),它的性能可以做到接近原生,并且又不受原生控件的限制,在不同平臺(tái)上能夠做到 UI 統(tǒng)一。
Flutter 就是這樣的一個(gè)開(kāi)發(fā)框架。
一個(gè)跨平臺(tái) UI 解決方案
Flutter 是由 Google 開(kāi)發(fā)的,一個(gè)跨平臺(tái) UI 解決方案。換句話(huà)說(shuō),它原則上只管 UI 的問(wèn)題,如果涉及到平臺(tái)本身的一些功能,比如調(diào)用藍(lán)牙、攝像頭,一般還是需要原生代碼去操作。但現(xiàn)在也會(huì)有一些第三方庫(kù)幫我們解決這些問(wèn)題。
繪圖引擎 Skia
Flutter 使用 Skia 作為它的繪圖引擎。Skia 已經(jīng)被 Google 收購(gòu),目前很多 Google 旗下的產(chǎn)品都是用 Skia 繪制的,包括 Android。
Android 內(nèi)置了 Skia,但 iOS 沒(méi)有,所以在打 iOS 安裝包的時(shí)候,會(huì)把 Skia 一起打進(jìn)去。這就導(dǎo)致了,用同一份 Flutter 代碼打包之后,iOS 的包要比 Android 的包大一些。
開(kāi)發(fā)語(yǔ)言 Dart
Flutter 使用的開(kāi)發(fā)語(yǔ)言,叫 Dart。Dart 也是 Google 自家的,它是一門(mén)面向?qū)ο蟮恼Z(yǔ)言,從它身上會(huì)看到一些其他開(kāi)發(fā)語(yǔ)言的影子。學(xué)習(xí)起來(lái)難度不大的。
前面講跨平臺(tái)方案的時(shí)候,可以發(fā)現(xiàn)別的方案基本都是用 JavaScript 作為開(kāi)發(fā)語(yǔ)言的,但為什么 Flutter 不用?就因?yàn)?Dart 是谷歌自家的嗎?這個(gè)問(wèn)題先留著,我們后面會(huì)提到。
這里部分就簡(jiǎn)單點(diǎn)帶過(guò)了,具體的搭建流程可以在官網(wǎng)查看:
主要的搭建步驟如下:
下載 Flutter SDK
官網(wǎng)下載地址:
由于在國(guó)內(nèi)訪(fǎng)問(wèn)可能受限,官方為中國(guó)開(kāi)發(fā)者搭建了鏡像:
更新環(huán)境變量
解壓后,將 flutter\bin 的全路徑添加到環(huán)境變量 PATH 中。
安裝開(kāi)發(fā)工具
理論上,任何文本編輯器都可以用來(lái)開(kāi)發(fā) Flutter 應(yīng)用,但推薦的開(kāi)發(fā)工具是 Android Studio、IntelliJ 以及 VS Code。因?yàn)樵谶@些開(kāi)發(fā)工具上,可以安裝官方的 Flutter 和 Dart 插件,得到更好的開(kāi)發(fā)體驗(yàn)。文章里使用 Android Studio 來(lái)演示。
如果你打算開(kāi)發(fā) iOS 應(yīng)用,則還需要安裝 Xcode。
安裝插件
在開(kāi)發(fā)工具的插件設(shè)置中,安裝上面說(shuō)到的 Flutter 和 Dart 插件。Flutter 插件用于支持 Flutter 的運(yùn)行、調(diào)試、熱重載等功能,而 Dart 插件則提供了代碼的輸入校驗(yàn)、代碼補(bǔ)全等功能。
萬(wàn)物始于 Hello World,我們先來(lái)創(chuàng)建一個(gè)顯示 Hello World 的 Flutter 項(xiàng)目。
在 Android Studio 的歡迎頁(yè)面選擇 Start a new Flutter project ,或者通過(guò)菜單欄的 File New New Flutter Project ,創(chuàng)建一個(gè)新的 Flutter 項(xiàng)目。
創(chuàng)建好的項(xiàng)目里面包含了 android 和 ios 兩個(gè)文件夾,它們是標(biāo)準(zhǔn)的 Android 和 iOS 項(xiàng)目。我們的 Flutter 代碼,存放在 lib 文件夾里。項(xiàng)目創(chuàng)建好后,會(huì)默認(rèn)帶一個(gè)計(jì)數(shù)器的示例,我們不管它,把 main.dart 的代碼改成 Hello World:
啟動(dòng)一個(gè)模擬器,或者連上真機(jī),點(diǎn)擊 Run 運(yùn)行一下,就能看這樣一個(gè)界面了:
具體代碼先混個(gè)眼熟就好,具體的后面會(huì)再講到。
在寫(xiě) Flutter 之前,還要先跟大家簡(jiǎn)單介紹一下 Dart 的語(yǔ)法。如果你有 Java 或 JavaScript 的開(kāi)發(fā)經(jīng)驗(yàn),以及面向?qū)ο蟮木幊趟枷耄瑢W(xué)起來(lái)是很快的。
我們可以在 test 文件夾下新建一個(gè) dart 文件,用來(lái)寫(xiě)測(cè)試代碼。
指定類(lèi)型
var
但和 JavaScript 不同的是,以下代碼在 JavaScript 是不會(huì)報(bào)錯(cuò)的,但在 Dart 里會(huì)報(bào)錯(cuò):
Object
如果非要上面這樣寫(xiě),那也可以。把 var 換成 Object 就不報(bào)錯(cuò)了:
和 Java 類(lèi)似,Object 是所有對(duì)象的根基類(lèi)。但是這樣的話(huà),如果想打印一下 num 的字符串長(zhǎng)度,是會(huì)報(bào)錯(cuò)的:
因?yàn)?length 是屬于 String 的,但系統(tǒng)只知道 num 是一個(gè)對(duì)象,并不知道它是一個(gè) String。
dynamic
如果還是非要這樣寫(xiě),那也可以。Dart 有一個(gè)特有的關(guān)鍵字 dynamic,把 Object 改成 dynamic 就不報(bào)錯(cuò)了:
我們運(yùn)行一下這個(gè)文件,可以在控制臺(tái)看到正確打印出了字符串長(zhǎng)度。
函數(shù)
dynamic
在 Dart 里,函數(shù)也是可以不寫(xiě)返回類(lèi)型的,不寫(xiě)的話(huà)會(huì)被當(dāng)做 dynamic 來(lái)處理。這樣的話(huà),函數(shù)的類(lèi)型就是 return 的類(lèi)型,如果沒(méi)有 return 則是 void 類(lèi)型。比如可以這樣:
運(yùn)行之后是能正確打印出字符串長(zhǎng)度的。
用于傳參
Dart 里的函數(shù)也是一個(gè)對(duì)象,所以可以把函數(shù)作為參數(shù)來(lái)傳遞,比如:
可選參數(shù)
在 Dart 的函數(shù)傳參里,有一個(gè)叫可選參數(shù)的概念,我們以文字控件 Text 為例,在源碼里可以看到 Text 的構(gòu)造函數(shù)是這樣的:
首先,在參數(shù)里有一個(gè) data,它是要顯示的文字內(nèi)容,是一個(gè)必填項(xiàng)。而 data 后面的一堆參數(shù),是用一個(gè)大括號(hào)括起來(lái)的,這些參數(shù)就叫做可選參數(shù),意思是這些參數(shù)可傳可不傳。
假如我們要顯示一個(gè)比較長(zhǎng)的文字,又想限制它最多顯示兩行,就可以這樣來(lái)創(chuàng)建一個(gè) Text:
可選參數(shù),在 Flutter 里面用的非常多。
異步
Future
在 Dart 里使用 Future 來(lái)處理異步任務(wù),比如我們現(xiàn)在延時(shí)一秒打印 666,代碼如下:
Future 的語(yǔ)法和 Promise 非常像。任務(wù)執(zhí)行成功會(huì)調(diào)用 then,執(zhí)行失敗會(huì)調(diào)用 catchError,而無(wú)論成功還是失敗,都會(huì)調(diào)用 whenComplete。
async/await
如果你不喜歡上面那種寫(xiě)法,或者是想把異步轉(zhuǎn)成同步,就可以用 async 和 await 這兩個(gè)關(guān)鍵字來(lái)轉(zhuǎn)換。
我們把上面的代碼轉(zhuǎn)換一下,寫(xiě)一個(gè) getString 方法,返回的類(lèi)型是 Future,它會(huì)延時(shí)返回一個(gè)字符串。在 main 函數(shù)后面加上 async 關(guān)鍵字,在 getString() 前面加上 await,代碼如下:
運(yùn)行之后可以看到,能正常延時(shí)一秒后,把字符串打印出來(lái)。這里 getString() 返回的類(lèi)型是 Future,而 await getString() 則是返回了延時(shí)之后返回的字符串。await 要在 async 的函數(shù)里面才能使用。
async 和 await 其實(shí)是一個(gè)語(yǔ)法糖,它最終也是轉(zhuǎn)換成 Future 調(diào)用鏈的形式執(zhí)行的。
接下來(lái)回到 Flutter,F(xiàn)lutter 里最重要的一個(gè)概念是 Widget(下面翻譯作控件)。
在原生開(kāi)發(fā)里面,我們可能會(huì)在界面上區(qū)分,這是一個(gè) View,這是一個(gè) Layout,這是一個(gè) View Controller。但在 Flutter 里面,它們?nèi)紝儆谝粋€(gè)統(tǒng)一的模型 Widget。可以說(shuō),在 Flutter 界面里,所有東西都是 Widget。
以前學(xué)面向?qū)ο蟮臅r(shí)候,我們都聽(tīng)過(guò)一句話(huà),叫萬(wàn)物皆對(duì)象。我這里套用一下,在 Flutter 里, 萬(wàn)物皆控件 。
具體有哪些控件,我做了一下簡(jiǎn)單的分類(lèi)。
根控件
所有的控件都屬于 StatefulWidget 或 StatelessWidget 。它們的區(qū)別是,StatefulWidget 擁有狀態(tài) State ,而 StatelessWidget 沒(méi)有。
StatefulWidget
當(dāng)一個(gè)控件是可變的時(shí)候,就要使用 StatefulWidget 來(lái)構(gòu)建。StatefulWidget 本身不可變,但它持有的狀態(tài) State 是可變的。
StatelessWidget
當(dāng)一個(gè)控件狀態(tài)是固定不可變的時(shí)候,就可以使用 StatelessWidget。前面我們寫(xiě)的 Hello World 就是使用 StatelessWidget。
容器控件
容器類(lèi)控件一般是將某些屬性或配置,作用在它的子控件上,比如控件所在的寬高、背景、位置等。
常用的容器控件有 Container、Center、Padding 等。
布局控件
布局控件可以類(lèi)比作原生開(kāi)發(fā)中的 Layout,通常它會(huì)擁有一個(gè) children 的屬性,用于接收一個(gè)控件數(shù)組,對(duì)這些控件進(jìn)行特定的排版。
常用的布局控件有 Row、Column、Stack、Flex 等。
基礎(chǔ)控件
基礎(chǔ)控件就是常用的文字、按鈕、圖片等控件。
常用的基礎(chǔ)控件有 Text、TextField、Button、Image 等。
功能控件
在 Flutter 里還有一類(lèi)控件,它們不影響 UI 布局,但帶有一些特定的功能,比如頁(yè)面跳轉(zhuǎn)、事件監(jiān)聽(tīng)、定義主題等。我們把這一類(lèi)控件稱(chēng)作功能控件。
常用的功能控件有 Navigator、NotificationListener、Theme 等。
開(kāi)始寫(xiě) Flutter 代碼了。還記不記得,在 Flutter 項(xiàng)目創(chuàng)建之后,是自帶一個(gè)計(jì)數(shù)器 demo 的,現(xiàn)在我們用自己的代碼實(shí)現(xiàn)一遍。代碼修改成如下:
運(yùn)行之后,就可以看到這樣的界面了:
按鈕每點(diǎn)擊一次,數(shù)字就會(huì)加一。下面我們來(lái)分析一下這段代碼,看下里面用到的一些 Widget。
StatefulWidget
由于頁(yè)面中的數(shù)字是跟隨狀態(tài)變化的,所以該頁(yè)面改用 StatefulWidget。StatefulWidget 并不會(huì)直接返回一個(gè) Widget,而是返回狀態(tài) State,在 State 里再返回 Widget。
Scaffold
Scaffold 是一個(gè)標(biāo)準(zhǔn)的 Material Design 頁(yè)面,它包含了標(biāo)題欄、浮動(dòng)按鈕、側(cè)滑菜單、底部導(dǎo)航欄等配置。我們這里用到了標(biāo)題欄 appBar、頁(yè)面內(nèi)容 body、浮動(dòng)按鈕 floatingActionButton。
AppBar
AppBar 就是標(biāo)題欄,通過(guò)查看控件的構(gòu)造方法,我們可以知道它可配置的屬性。
AppBar 的可選參數(shù)除了標(biāo)題 title,還可以配置標(biāo)題前的內(nèi)容 leading,右側(cè)的操作按鈕 anctions,控件垂直高度 elevation 等。我們只傳了 title,其他屬性都用默認(rèn)值。
Center
Center 是一個(gè)容器類(lèi)控件,它的作用就是讓它的子控件居中顯示。
FloatingActionButton
熟悉安卓開(kāi)發(fā)的應(yīng)該對(duì)這個(gè)控件比較熟悉,它就是頁(yè)面右下角一個(gè)特定樣式的 Button,參數(shù)里面的 onPressed 是一個(gè)必填項(xiàng),要傳一個(gè)點(diǎn)擊之后的回調(diào)函數(shù)。
根據(jù)這個(gè)例子,下面給大家介紹一下 Flutter 兩個(gè)比較重要的特性。
點(diǎn)擊 Button 之后,我們把 num 變量加一,并使用 setState 通知狀態(tài)發(fā)生了改變,F(xiàn)lutter 會(huì)根據(jù)新的狀態(tài)更新 UI。如果有接觸過(guò)小程序開(kāi)發(fā),setState 就和小程序的 setData 類(lèi)似。
在 Flutter 里面我們不需要用 set 方法來(lái)更新 UI,可變控件是和狀態(tài)綁定的,這就是 Flutter 的響應(yīng)式 UI 編程。
在 Android Q 和 iOS 13 里都加入了暗黑模式,我們也換一個(gè)暗黑主題來(lái)玩一下。MaterialApp 里有一個(gè) theme 的屬性,我們把它配置一下:
這次改完之后不點(diǎn) Run 了,我們點(diǎn)一下閃電圖標(biāo) Flutter Hot Reload ,就能看到界面發(fā)生了變化:
這就是 Flutter 的 熱重載 ,在修改完代碼之后,通過(guò)熱重載就能馬上在設(shè)備上看到修改結(jié)果,可以很大程度上增加開(kāi)發(fā)效率。
下面再給大家介紹幾個(gè) Flutter 里的常見(jiàn)操作。
在 Flutter 里,使用 Navigator 來(lái)管理頁(yè)面跳轉(zhuǎn),比如要跳轉(zhuǎn)到一個(gè) NewPage 可以這樣寫(xiě):
進(jìn)棧使用 push,出棧則是 pop。
使用 MaterialPageRoute 會(huì)模擬出 Android 上頁(yè)面跳轉(zhuǎn)的過(guò)場(chǎng)效果。
我們來(lái)看看怎么顯示一張本地圖片。
先在根目錄新建一個(gè)存放圖片的文件夾,比如叫 images,把圖片 picture.png 放進(jìn)去。
找到根目錄下的 pubspec.yaml 文件,這個(gè)便是 Flutter 依賴(lài)配置文件,我們需要在這里配置一下剛才的圖片:
這樣,我們就能使用 Image 控件把這張圖片顯示出來(lái)了:
和 node 的 npm 以及 Android 的 jcenter 類(lèi)似,F(xiàn)lutter 也擁有一個(gè)公共倉(cāng)庫(kù) pub.dev。pub.dev 是 Google 官方的 Dart 倉(cāng)庫(kù),在上面可以找到我們需要的包和插件。
Flutter 本身沒(méi)有 Toast,我們來(lái)接入一個(gè)。在 pub.dev 上搜索后,我決定使用 fluttertoast:
按照說(shuō)明,在 pubspec.yaml 文件里的 dependencies 下配置:
點(diǎn)一下 Android Studio 右上角的 Packages get 同步之后就可以使用了:
我們上面使用的都是 Material Design 的控件,它們都是在 flutter/material.dart 包里面的。如果要使用 iOS 風(fēng)格的控件,則要用到 flutter/cupertino.dart 包:
iOS 風(fēng)格的控件,基本都以 Cupertino 開(kāi)頭。我們把計(jì)時(shí)器頁(yè)面里的控件替換一下:
效果如下:
代碼的部分就到這里了,接下來(lái)跟大家聊一下編譯方式,編程語(yǔ)言的編譯方式有兩種。
關(guān)于它們孰優(yōu)孰劣,就要看從哪個(gè)角度去對(duì)比了。JIT 的話(huà),它的一大特點(diǎn)就是支持動(dòng)態(tài)發(fā)布代碼,也就是支持熱更新。但要是從性能的角度考慮,AOT 會(huì)更好,因?yàn)樵谶\(yùn)行的時(shí)候不用再進(jìn)行編譯的操作的,運(yùn)行的效率會(huì)更高一些。
回到我們一開(kāi)始的時(shí)候留下的問(wèn)題,為什么別的跨平臺(tái)方案都是用 JavaScript,而 Flutter 要用 Dart 來(lái)開(kāi)發(fā)。JavaScript 的編譯方式是 JIT 的,它不支持 AOT。而 Dart 同時(shí)支持 JIT 和 AOT。
Flutter 在開(kāi)發(fā)階段使用 JIT,讓我們用上了熱重載,增加了開(kāi)發(fā)效率。在打包時(shí)改用 AOT,保證了正式版應(yīng)用的性能。
最后講一下大家比較關(guān)心的一個(gè)東西,F(xiàn)lutter 是否支持熱更新?前面說(shuō)到 Dart 支持 JIT,所以從技術(shù)層面它是支持的。但是目前是不支持的,在官方的計(jì)劃文檔中,可以看到:
至于原因,官方在這里進(jìn)行了說(shuō)明。總的來(lái)說(shuō),是由于政策的限制,以及出于對(duì)性能和安全性的考慮,暫時(shí)不支持了。
到這就結(jié)束啦。由于想把 Flutter 基礎(chǔ)在一篇內(nèi)講完,沒(méi)有涉及太多細(xì)節(jié),如果要寫(xiě) Flutter 代碼還需要深入學(xué)習(xí)。但相信理解之后再學(xué),會(huì)輕松很多。
新聞標(biāo)題:flutter產(chǎn)品,flutter介紹
鏈接URL:http://chinadenli.net/article21/dsigpcd.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機(jī)、網(wǎng)站設(shè)計(jì)公司、外貿(mào)建站、搜索引擎優(yōu)化、網(wǎng)站排名、Google
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)