flutter web有三種渲染模式,auto 、html 和 canvaskit。
10余年品牌的成都網(wǎng)站建設(shè)公司,上千家企業(yè)網(wǎng)站設(shè)計經(jīng)驗(yàn).價格合理,可準(zhǔn)確把握網(wǎng)頁設(shè)計訴求.提供定制網(wǎng)站建設(shè)、成都做商城網(wǎng)站、微信平臺小程序開發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)等服務(wù),我們設(shè)計的作品屢獲殊榮,是您值得信賴的專業(yè)網(wǎng)站制作公司。
flutter build web命令默認(rèn)的渲染模式為auto,這種模式在移動端使用html渲染,在pc端使用canvaskit渲染。
目前我的flutter版本是2.5.2,pc端瀏覽器使用canvaskit渲染時中文會出現(xiàn)短暫的亂碼(方塊叉號),像這樣:
我們可以指定渲染模式為html,就不會有這個問題了,命令如下:
指定渲染模式為canvaskit的命令為:
2021.10.21:flutter web對中文的支持貌似不太好,在手機(jī)瀏覽器調(diào)試web項目時,textfield hinttext有中文輸入會有卡頓bug
前言
最近街邊討論買基金大佬們又多起來了,一些技術(shù)交流群也時不時看到某某某大佬在討論股票,看來最近行情很好啊,雖然我不懂交易,但我總覺得可以做些什么來彌補(bǔ)我的不足,于是有了接下來要跟大家分享的“盯盤小工具”。
準(zhǔn)備開干
那么接下來我的目標(biāo)是開發(fā)一款PC端的桌面盯盤小工具,特點(diǎn)首先就是小、方便整天盯著電腦屏幕的白領(lǐng)們打開瞧瞧,省去費(fèi)事各種操作;然后就是無需關(guān)注太多費(fèi)腦筋的指標(biāo),所以能夠顯示名稱和漲跌幅即可。有的上面的需求后,那就可以開始搬磚了,但是對于我這種只懂點(diǎn)Android皮毛又沒做過桌面應(yīng)用的人來說,簡直是比登天還難,那該咋辦?在夜深人靜時,我恍然想起了Flutter,沒錯先來一張圖:
還記得當(dāng)時看Flutter的時候還是1.2版本,如今回過頭來看,已經(jīng)不是曾經(jīng)那個Flutter了。
搬磚
為了實(shí)現(xiàn)這個小小的業(yè)余需求并且又能學(xué)習(xí)Flutter,于是我白天下班回來又開始不同場景不同程序語言的搬磚,重新安裝了Flutter的最新開發(fā)環(huán)境,重新學(xué)習(xí)Flutter開發(fā)-萬物皆widget。
功夫不負(fù)有心人
效果圖展示
當(dāng)前為最初版本,很多功能還不夠完善,后續(xù)目標(biāo)就是完善及優(yōu)化,
GitHub項目地址:
致謝
為了實(shí)現(xiàn)這個小小的業(yè)余需求并且又能學(xué)習(xí)Flutter,我也參考了很多Flutter大佬的開源項目,在此感謝所有優(yōu)秀的開源項目 _ 。
文/陳爐軍
整理/LiveVideoStack
大家好,我是阿里巴巴閑魚事業(yè)部的陳爐軍,本次分享的主題是Flutter浪潮下的音視頻研發(fā)探索,主要內(nèi)容是針對閑魚APP在當(dāng)下流行的跨平臺框架Flutter的大規(guī)模實(shí)踐,介紹其在音視頻領(lǐng)域碰到的一些困難以及解決方案。
分享內(nèi)容主要分為四個方面,首先會對Flutter有一個簡單介紹以及選擇Flutter作為跨平臺框架的原因,其次會介紹Flutter中與音視頻關(guān)系非常大的外接紋理概念,以及對它做出的一些優(yōu)化。之后會對閑魚在音視頻實(shí)踐過程中碰到的一些Flutter問題提出了一些解決方案——TPM音視頻框架。最后是閑魚Flutter多媒體開源組件的介紹。
Flutter
Flutter是一個跨平臺框架,以往的做法是將音頻、視頻和網(wǎng)絡(luò)這些模塊都下沉到C++層或者ARM層,在其上封裝成一個音視頻的SDK,供UI層的PC、iOS和Android調(diào)用。
而Flutter做為一個UI層的跨平臺框架,顧名思義就是在UI層也實(shí)現(xiàn)了一個跨平臺開發(fā)。可以預(yù)想的是未Flutter發(fā)展的好的話,會逐漸變?yōu)橐粋€從底層到UI層的一個全鏈路的跨平臺開發(fā),技術(shù)人員分別負(fù)責(zé)SDK和UI層的開發(fā)。
在Flutter之前已經(jīng)有很多跨平臺UI解決方案,那為什么選擇Flutter呢?
我們主要考慮性能和跨平臺的能力。
以往的跨平臺方案比如Weex,ReactNative,Cordova等等因?yàn)榧軜?gòu)的原因無法滿足性能要求,尤其是在音視頻這種性能要求幾乎苛刻的場景。
而諸如Xamarin等,雖然性能可以和原生App一致,但是大部分邏輯還是需要分平臺實(shí)現(xiàn)。
我們可以看一下,為什么Flutter可以實(shí)現(xiàn)高性能:
原生的native組件渲染以IOS為例,蘋果的UIKit通過調(diào)用平臺自己的繪制框架QuaztCore來實(shí)現(xiàn)UI的繪制,圖形繪制也是調(diào)用底層的API,比如OpenGL、Metal等。
而Flutter也是和原生API邏輯一致,也是通過調(diào)用底層的繪制框架層SKIA實(shí)現(xiàn)UI層。這樣相當(dāng)于Flutter他自己實(shí)現(xiàn)了一套UI框架,提供了一種性能超越原生API的跨平臺可能性。
但是我們說一個框架最終性能怎樣,其實(shí)取決于設(shè)計者和開發(fā)者。至于現(xiàn)在到底是一個什么狀況:
在閑魚的實(shí)踐中,我們發(fā)現(xiàn)在正常的開發(fā)沒有特意的去優(yōu)化UI代碼的情況下,在一些低端機(jī)上,F(xiàn)lutter界面的流暢性是比Native界面要好的。
雖然現(xiàn)在閑魚某些場景下會有卡頓閃退等情況,但是這是一個新事物發(fā)展過程中的必然問題,我們相信未來性能肯定不會成為限制Flutter發(fā)展的瓶頸的。
在閑魚實(shí)踐Flutter的過程中,混合棧和音視頻是其中比較難解決的兩個問題,混合棧是指一個APP在Flutter過程中不可能一口氣將所有業(yè)務(wù)全部重寫為Flutter,所以這是一個逐步迭代的過程,這期間原生native界面與Flutter界面共存的狀態(tài)就稱之為混合棧。閑魚在混合棧上也有一些比較好的輸出,例如FlutterBoost。
外接紋理
在講音視頻之前需要簡要介紹一下外接紋理的概念,我們將它稱之為是Flutter和Frame之間的橋梁。
Flutter渲染一幀屏幕數(shù)據(jù)首先要做的是,GPU發(fā)出的VC信號在Flutter的UI線程,通過AOT編譯的機(jī)器碼結(jié)合當(dāng)前Dart Runtime,生成Layer Tree UI樹,Layer Tree上每一個葉子節(jié)點(diǎn)都代表了當(dāng)前屏幕上所需要渲染的每一個元素,包含了這些元素渲染所需要的內(nèi)容。將Layer Tree拋給GPU線程,在GPU線程內(nèi)調(diào)用Skia去完成整個UI的渲染過程。Layer Tree中有PictureLayer和TextureLayer兩個比較重要的節(jié)點(diǎn)。PictureLayer主要負(fù)責(zé)屏幕圖片的渲染,F(xiàn)lutter內(nèi)部實(shí)現(xiàn)了一套圖片解碼邏輯,在IO線程將圖片讀取或者從網(wǎng)絡(luò)上拉取之后,通過解碼能夠在IO線程上加載出紋理,交給GPU線程將圖片渲染到屏幕上。但是由于音視頻場景下系統(tǒng)API太過繁多,業(yè)務(wù)場景過于復(fù)雜。Flutter沒有一套邏輯去實(shí)現(xiàn)跨平臺的音視頻組件,所以說Flutter提出了一種讓第三方開發(fā)者來實(shí)現(xiàn)音視頻組件的方式,而這些音視頻組件的視頻渲染出口,就是TextureLayer。
在整個Layer Tree渲染的過程中,TextureLayer的數(shù)據(jù)紋理需要由外部第三方開發(fā)者來指定,可以把視頻數(shù)據(jù)和播放器數(shù)據(jù)送到TextureLayer里,由Flutter將這些數(shù)據(jù)渲染出來。
TextureLayer渲染過程:首先判斷Layer是否已經(jīng)初始化,如果沒有就創(chuàng)建一個Texture,然后將Texture Attach到一個SufaceTexture上。
這個SufaceTexture是音視頻的native代碼可以獲取到的對象,通過這個對象創(chuàng)建的Suface,我們可以將視頻數(shù)據(jù)、攝像頭數(shù)據(jù)解碼放到Suface中,然后Flutter端通過監(jiān)聽SufaceTexture的數(shù)據(jù)更新就可以順利把剛才創(chuàng)建的數(shù)據(jù)更新到它的紋理中,然后再將紋理交給SKIA渲染到屏幕上。
然而我們?nèi)绻枰肍lutter實(shí)現(xiàn)美顏,濾鏡,人臉貼圖等等功能,就需要將視頻數(shù)據(jù)讀取出來,更新到紋理中,再將GPU紋理經(jīng)過美顏濾鏡處理后生成一個處理后的紋理。按Flutter提供的現(xiàn)有能力,必須先將紋理中的數(shù)據(jù)從GPU讀出到CPU中,生成Bitmap后再寫入Surface中,這樣在Flutter中才能順利的更新到視頻數(shù)據(jù),這樣做對系統(tǒng)性能的消耗很大。
通過對Flutter渲染過程分析,我們知道Flutter底層需要渲染的數(shù)據(jù)就是GPU紋理,而我們經(jīng)過美顏濾鏡處理完成以后的結(jié)果也是GPU紋理,如果可以將它直接交給Flutter渲染,那就可以避免GPU-CPU-GPU這樣的無用循環(huán)。這樣的方法是可行的,但是需要一個條件,就是OpenGL上下文共享。
OpenGL
在說上下文之前,得提到一個和上線文息息相關(guān)的概念:線程。
Flutter引擎啟動后會啟動四個線程:
第一個線程是UI線程,這是Flutter自己定義的UI線程,主要負(fù)責(zé)GPU發(fā)出的VSync信號時候用當(dāng)前Dart編譯的機(jī)器碼和當(dāng)前運(yùn)行環(huán)境創(chuàng)建出Layer Tree。
還有就是IO線程和GPU線程。和大部分OpenGL處理解決方案中一樣,F(xiàn)lutter也采取一個線程責(zé)資源加載,一部分負(fù)責(zé)資源渲染這種思路。
兩個線程之間紋理共享有兩種方式。一種是EGLImage(IOS是 CVOpenGLESTextureCache)。一種是OpenGL Share Context。Flutter通過Share Context來實(shí)現(xiàn)紋理共享,將IO線程的Context和GPU線程的Context進(jìn)行Share,放到同一個Share Group下面,這樣兩個線程下資源是互相可見可以共享的。
Platform線程是主線程,F(xiàn)lutter中有一個很奇怪的設(shè)定,GPU線程和主線程共用一個Context。并且在主線程也有很多OpenGL 操作。
這樣的設(shè)計會給音視頻開發(fā)帶來很多問題,后面會詳細(xì)說。
音視頻端美顏處理完成的OpenGL紋理能夠讓Flutter直接使用的條件就是Flutter的上下文需要和平臺音視頻相關(guān)的OpenGL上下文處在一個Share Group下面。
由于Flutter主線程的Context就是GPU的Context,所以在音視頻端主線程中有一些OpenGL操作的話,很有可能使Flutter整個OpenGL被破壞掉。所以需要將所有的OpenGL操作都限制在子線程中。
通過上述這兩個條件的處理,我們就可以在沒有增加GPU消耗的前提下實(shí)現(xiàn)美顏和濾鏡等等功能。
TPM
在經(jīng)過demo驗(yàn)證之后,我們將這個方案應(yīng)用到閑魚音視頻組件中,但改造過程中發(fā)現(xiàn)了一些問題。
上圖是攝像頭采集數(shù)據(jù)轉(zhuǎn)換為紋理的一段代碼,其中有兩個操作:首先是切進(jìn)程,將后面的OpenGL操作都切到cameraQueue中。然后是設(shè)置一次上下文。然后這種限制條件或者說是潛規(guī)則往往在開發(fā)過程中容易被忽略的。而這個條件一旦忽略后果就是出現(xiàn)一些莫名其妙的詭異問題極難排查。因此我們就希望能抽象出一套框架,由框架本身實(shí)現(xiàn)線程的切換、上下文和模塊生命周期等的管理,開發(fā)者接入框架以后只需要安心實(shí)現(xiàn)自己的算法,而不需要關(guān)心這些潛規(guī)則還有其他一些重復(fù)的邏輯操作。
在引入Flutter之前閑魚的音視頻架構(gòu)與大部分音視頻邏輯一樣采用分層架構(gòu):
1:底層是一些獨(dú)立模塊
2:SDK層是對底層模塊的封裝
3:最上層是UI層。
引入Flutter之后,通過分析各個模塊的使用場景,我們可以得出一個假設(shè)或者說是抽象:音視頻應(yīng)用在終端上可以歸納為視頻幀解碼之后視頻數(shù)據(jù)幀在各個模塊之間流動的過程,基于這種假設(shè)去做Flutter音視頻框架的抽象。
咸魚Flutter多媒體開源組件
整個Flutter音視頻框架抽象分為管線和數(shù)據(jù)的抽象、模塊的抽象、線程統(tǒng)一管理和上下文同一管理四部分。
管線,其實(shí)就是視頻幀流動的管道。數(shù)據(jù),音視頻中涉及到的數(shù)據(jù)包括紋理、Bit Map以及時間戳等。結(jié)合現(xiàn)有的應(yīng)用場景我們定義了管線流通數(shù)據(jù)以Texture為主數(shù)據(jù),同時可以選擇性的添加Bit Map等作為輔助數(shù)據(jù)。這樣的數(shù)據(jù)定義方式,避免重復(fù)的創(chuàng)建和銷毀紋理帶來的性能開銷以及多線程訪問紋理帶來的一些問題。也滿足一些特殊模塊對特殊數(shù)據(jù)的需求。同時也設(shè)計了紋理池來管理管線中的紋理數(shù)據(jù)。
模塊:如果把管線和數(shù)據(jù)比喻成血管和血液,那框架音視頻的場景就可以比喻成器官,我們根據(jù)模塊所在管線的位置抽象出采集、處理和輸出三個基類。這三個基類里實(shí)現(xiàn)了剛才說的線程切換,上下文切換,格式轉(zhuǎn)換等等共同邏輯,各個功能模塊通過集成自這些基類,可以避免很多重復(fù)勞動。
線程:每一個模塊初始化的時候,初始化函數(shù)就會去線程管理的模塊去獲取自己的線程,線程管理模塊可以決定給初始化函數(shù)分配新的線程或者已經(jīng)分配過其他模塊的線程。
這樣有三個好處:
一是可以根據(jù)需要去決定一個線程可以掛載多少模塊,做到線程間的負(fù)載均衡。第二,多線程并發(fā)式能夠保證模塊內(nèi)的OpenGL操作是在當(dāng)前線程內(nèi)而不會跑到主線程去,徹底避免Flutter的OpenGL 環(huán)境被破壞。第三,多線程并行可以充分利用CPU多核架構(gòu),提升處理速度。
從Flutter端修改Flutter引擎將Context取出后,根據(jù)Context創(chuàng)建上下文的統(tǒng)一管理模塊,每一個模塊在初始化的時候會獲取它的線程,獲取之后會調(diào)用上下文管理模塊獲取自己的上下文。這樣可以保證每一個模塊的上下文都是與Flutter的上下文進(jìn)行Share的,每個模塊之間資源都是共享可見的,F(xiàn)lutter和音視頻native之間也是互相共享可見的。
基于上述框架如果要實(shí)現(xiàn)一個簡單的場景,比如畫面實(shí)時預(yù)覽和濾鏡處理功能,
1:需要選擇功能模塊,功能模塊包括攝像頭模塊、濾鏡處理模塊和Flutter畫面渲染模塊,
2:需要配置模塊參數(shù),比如采集分辨率、濾鏡參數(shù)和前后攝像頭設(shè)置等,
3:在創(chuàng)建視頻管線后使用已配置的參數(shù)創(chuàng)建模塊
4:最后管線搭載模塊,開啟管線就可以實(shí)現(xiàn)這樣簡單的功能。
上圖為整個功能實(shí)現(xiàn)的代碼和結(jié)構(gòu)圖。
結(jié)合上述音視頻框架,閑魚實(shí)現(xiàn)了Flutter多媒體開源組件。
組要包含四個基本組件分別是:
1:視頻圖像拍攝組件
2:播放器組件
3:視頻圖像編輯組件
4:相冊選擇組件
現(xiàn)在這些組件正在走內(nèi)部開源流程。預(yù)計9月份,相冊和播放器會實(shí)現(xiàn)開源。
后續(xù)展望和規(guī)劃
1:實(shí)現(xiàn)開頭所說的從底層SDK到UI的全鏈路的跨端開發(fā)。目前底層框架層和模塊層都是各個平臺各自實(shí)現(xiàn),反而是Flutter的UI端進(jìn)行了跨平臺的統(tǒng)一,所以后續(xù)會將底層也按照音視頻常用做法把邏輯下沉到C++層,盡可能的實(shí)現(xiàn)全鏈路跨平臺。
2:第二部分內(nèi)容為開源共建,閑魚開源的內(nèi)容不僅包括拍攝、編輯組件,還包括了很多底層模塊,希望有開發(fā)者在基于Flutter開發(fā)音視頻應(yīng)用時可以充分利用閑魚開源出的音視頻模塊能力,搭建APP框架,開發(fā)者只要去負(fù)責(zé)實(shí)現(xiàn)特殊需求模塊就可以,盡可能的減少重復(fù)勞動。
在前端項目開發(fā)過程中,現(xiàn)在很少有人會使用原生的CSS來搭建頁面,總歸都會引入一些前端UI框架以減少代碼的書寫。一般為了方便自己的使用,很多大公司都有自己的一套UI框架,同時也會把其開源出來。下面就是最近經(jīng)常使用并且很流行的一些前端UI框架,總有一款適合你:
Mint UI
Mint UI
Mint UI是餓了么團(tuán)隊開發(fā)的基于Vue .js的移動端UI框架,它包含豐富的 CSS 和 JS 組件,能夠滿足日常的移動端開發(fā)需要。
WeUI
WeUI是一套同微信原生視覺體驗(yàn)一致的基礎(chǔ)樣式庫,由微信官方設(shè)計團(tuán)隊為微信內(nèi)網(wǎng)頁和微信小程序量身設(shè)計,令用戶的使用感知更加統(tǒng)一。包含button、cell、dialog、toast、article、icon等各式元素。
Cube-ui
Cube-ui
Cube-ui 是滴滴團(tuán)隊開發(fā)的基于 Vue.js 實(shí)現(xiàn)的精致移動端組件庫。支持按需引入和后編譯,輕量靈活;擴(kuò)展性強(qiáng),可以方便地基于現(xiàn)有組件實(shí)現(xiàn)二次開發(fā)。
iView UI
iView UI
iView UI是一個強(qiáng)大的UI庫,基于vue,有很多實(shí)用的基礎(chǔ)組件比elementui的組件更豐富,主要服務(wù)于 PC 界面的中后臺產(chǎn)品。使用單文件的 Vue 組件化開發(fā)模式 基于 npm + webpack + babel 開發(fā),支持 ES2015 高質(zhì)量、功能豐富 友好的 API ,自由靈活地使用空間。
LayUI
LayUI
LayUI是一款采用自身模塊規(guī)范編寫的前端 UI 框架,遵循原生 HTML/CSS/JS 的書寫與組織形式,門檻極低,拿來即用。其外在極簡,卻又不失飽滿的內(nèi)在,體積輕盈,組件豐盈,從核心代碼到 API 的每一處細(xì)節(jié)都經(jīng)過精心雕琢,非常適合界面的快速開發(fā)。
ElementUI
ElementUI
Element是餓了么前端開源維護(hù)的Vue UI組件庫,組件齊全,基本涵蓋后臺所需的所有組件,文檔講解詳細(xì),例子也很豐富。 主要用于開發(fā)PC端的頁面,是一個質(zhì)量比較高的Vue UI組件庫。
at-ui
at-ui
at-ui 是一款阿里團(tuán)隊創(chuàng)建的基于 Vue 2.x 的前端 UI 組件庫,主要用于快速開發(fā) PC 網(wǎng)站產(chǎn)品。 它提供了一套 npm + webpack + babel 前端開發(fā)工作流程,CSS 樣式獨(dú)立,即使采用不同的框架實(shí)現(xiàn)都能保持統(tǒng)一的 UI 風(fēng)格。
amaze UI
amaze UI
Amaze UI 是一個移動優(yōu)先的跨屏前端框架。提供基礎(chǔ)樣式,網(wǎng)格,表格、表單、按鈕及常用組件樣式。是一個輕量級(所有 CSS 和 JS gzip 后 100 kB 左右)、?Mobile first?的前端框架
Vant UI
Vant UI
Vant UI是有贊前端團(tuán)隊基于有贊統(tǒng)一的規(guī)范實(shí)現(xiàn)的 Vue 組件庫,提供了一整套 UI 基礎(chǔ)組件和業(yè)務(wù)組件。通過 Vant,可以快速搭建出風(fēng)格統(tǒng)一的頁面,提升開發(fā)效率。
Flutter
Flutter
Flutter 是谷歌的移動端 UI 框架,可在極短的時間內(nèi)構(gòu)建 Android 和 iOS 上高質(zhì)量的原生級應(yīng)用。 Flutter 可與現(xiàn)有代碼一起工作, 它被世界各地的開發(fā)者和組織使用, 并且 Flutter 是免費(fèi)和開源的.
ionic
Ionic既是一個CSS框架也是一個Javascript UI庫,Ionic 是目前最有潛力的一款 HTML5 手機(jī)應(yīng)用開發(fā)框架。通過 SASS 構(gòu)建應(yīng)用程序,它 提供了很多 UI 組件來幫助開發(fā)者開發(fā)強(qiáng)大的應(yīng)用。 它使用 JavaScript MVVM 框架和 AngularJS 來增強(qiáng)應(yīng)用。提供數(shù)據(jù)的雙向綁定,使用它成為 Web 和移動開發(fā)者的共同選擇。
Dart的 IO 庫包含了文件讀寫的相關(guān)類,它屬于 Dart 語法標(biāo)準(zhǔn)的一部分,所以通過 Dart IO 庫,無論是 Dart VM 下的腳本還是 Flutter,都是通過 Dart IO 庫來操作文件的,不過和 Dart VM 相比,F(xiàn)lutter 有一個重要差異是文件系統(tǒng)路徑不同,這是因?yàn)镈art VM 是運(yùn)行在 PC 或服務(wù)器操作系統(tǒng)下,而 Flutter 是運(yùn)行在移動操作系統(tǒng)中,他們的文件系統(tǒng)會有一些差異。
Android 和 iOS 的應(yīng)用存儲目錄不同, PathProvider 插件提供了一種平臺透明的方式來訪問設(shè)備文件系統(tǒng)上的常用位置。該類當(dāng)前支持訪問兩個文件系統(tǒng)位置:
File代表一個整體的文件,他有三個構(gòu)造函數(shù),分別是:
文件讀取本身有兩種形式,一種是文本,一種是二進(jìn)制。
2.2.1 讀取文本內(nèi)容
如果是文本文件,F(xiàn)ile提供了readAsString、readAsLines、readAsStringSync、readAsLinesSync方法,讀取文本內(nèi)容
readAsString 一次性讀取所有文本
readAsLines 一行行的讀取文本
結(jié)果返回的是一個List,list中表示文件每行的內(nèi)容
readAsStringSync、readAsLinesSync同步讀取文本
2.2.2 讀取二進(jìn)制內(nèi)容
如果文件是二進(jìn)制,那么可以使用readAsBytes或者同步的方法readAsBytesSync:
dart中表示二進(jìn)制有一個專門的類型叫做Uint8List,他實(shí)際上表示的是一個int的List。
上面提到的讀取方式,都是一次性讀取整個文件,缺點(diǎn)就是如果文件太大的話,可能造成內(nèi)存空間的壓力。
所以File為我們提供了另外一種讀取文件的方法,流的形式來讀取文件.
示例
dart提供了open和openSync兩個方法來進(jìn)行隨機(jī)文件讀寫:
寫入和文件讀取一樣,可以一次性寫入或者獲得一個寫入句柄,然后再寫入。
一次性寫入的方法有四種,分別對應(yīng)字符串和二進(jìn)制
句柄形式可以調(diào)用openWrite方法,返回一個IOSink對象,然后通過這個對象進(jìn)行寫入:
默認(rèn)情況下寫入是會覆蓋整個文件的,但是可以通過下面的方式來更改寫入模式:
雖然dart中所有的異常都是運(yùn)行時異常,但是和java一樣,要想手動處理文件讀寫中的異常,則可以使用try,catch:
我們還是以計數(shù)器為例,實(shí)現(xiàn)在應(yīng)用退出重啟后可以恢復(fù)點(diǎn)擊次數(shù)。 這里,我們使用文件來保存數(shù)據(jù):
1.引入PathProvider插件;在pubspec.yaml文件中添加如下聲明:
執(zhí)行 flutter pub get
2.實(shí)現(xiàn)如下
參考:
當(dāng)前文章:flutterpc的簡單介紹
文章轉(zhuǎn)載:http://chinadenli.net/article22/dsdshjc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷、品牌網(wǎng)站建設(shè)、App開發(fā)、自適應(yīng)網(wǎng)站、網(wǎng)站內(nèi)鏈、全網(wǎng)營銷推廣
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)