您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)flutter是什么的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。
image
Flutter框架分三層
Framework,Engine, Embedder
Framework使用dart語(yǔ)言實(shí)現(xiàn),包括UI,文本,圖片,按鈕等Widgets,渲染,動(dòng)畫(huà),手勢(shì)等。此部分的核心代碼是flutter倉(cāng)庫(kù)下的flutter package,以及sky_engine倉(cāng)庫(kù)下的 io, async, ui(dart:ui庫(kù)提供了Flutter框架和引擎之間的接口)等package。
Engine使用C++實(shí)現(xiàn),主要包括:Skia, Dart 和 Text。
Skia是開(kāi)源的二維圖形庫(kù),提供了適用于多種軟硬件平臺(tái)的通用API。其已作為Google Chrome,Chrome OS,Android, Mozilla Firefox, Firefox OS等其他眾多產(chǎn)品的圖形引擎,支持平臺(tái)還包括Windows, macOS, iOS,Android,Ubuntu等。
Dart 部分主要包括:Dart Runtime,Garbage Collection(GC),如果是Debug模式的話(huà),還包括JIT(Just In Time)支持。Release和Profile模式下,是AOT(Ahead Of Time)編譯成了原生的arm代碼,并不存在JIT部分。
Text 即文本渲染,其渲染層次如下:衍生自 Minikin的libtxt庫(kù)(用于字體選擇,分隔行);HartBuzz用于字形選擇和成型;Skia作為渲染/GPU后端,在A(yíng)ndroid和Fuchsia上使用FreeType渲染,在iOS上使用CoreGraphics來(lái)渲染字體。
Embedder是一個(gè)嵌入層,通過(guò)該層把Flutter嵌入到各個(gè)平臺(tái)上去,Embedder的主要工作包括渲染Surface設(shè)置, 線(xiàn)程設(shè)置,以及插件等。平臺(tái)(如iOS)只是提供一個(gè)畫(huà)布,剩余的所有渲染相關(guān)的邏輯都在Flutter內(nèi)部,這就使得它具有了很好的跨端一致性。
Dart 也是一種VM語(yǔ)言,所以在每個(gè)運(yùn)行flutter的app中都有一個(gè)dart的運(yùn)行環(huán)境。編譯模式支持AOT和JIT。
Dart最開(kāi)始是google設(shè)計(jì)出來(lái)替代javascript的,但是并沒(méi)有湊效。后面Flutter選擇了Dart, 才使Dart活躍起來(lái)。
Dart語(yǔ)言的特點(diǎn):
單進(jìn)程異步事件模型
強(qiáng)類(lèi)型,可以類(lèi)型推斷
具有極高的運(yùn)行效率和優(yōu)秀的代碼運(yùn)行優(yōu)化的VM,根據(jù)早前的基準(zhǔn)測(cè)試,性能比肩 Java7 的JVM;
獨(dú)特的隔離區(qū)( Isolate ),可以實(shí)現(xiàn)多線(xiàn)程
面向?qū)ο缶幊?,一切?shù)據(jù)類(lèi)型均派生自 Object
運(yùn)算符重載,泛型支持
強(qiáng)大的 Future 和 Stream 模型,可以簡(jiǎn)單實(shí)現(xiàn)高效的代碼
Minix 特性,可以更好的實(shí)現(xiàn)方法復(fù)用
全平臺(tái)語(yǔ)言,可以很好的勝任移動(dòng)和前后端的開(kāi)發(fā)
在語(yǔ)法上,Dart 提供了很多便捷的操作
Flutter Engine自己不創(chuàng)建, 管理線(xiàn)程。Flutter Engine線(xiàn)程的創(chuàng)建和管理是由embedder負(fù)責(zé)的
Embeder提供四個(gè)Task Runner, 每個(gè)Task Runner負(fù)責(zé)不同的任務(wù),F(xiàn)lutter Engine不在乎Task Runner具體跑在哪個(gè)線(xiàn)程,但是它需要線(xiàn)程配置在整一個(gè)生命周期里面保持穩(wěn)定。也就是說(shuō)一個(gè)Runner最好始終保持在同一線(xiàn)程運(yùn)行
是Flutter Engine的主Task Runner,運(yùn)行Platform Task Runner的線(xiàn)程可以理解為是主線(xiàn)程。類(lèi)似于A(yíng)ndroid Main Thread或者iOS的Main Thread。對(duì)于Flutter Engine來(lái)說(shuō)Platform Runner所在的線(xiàn)程跟其它線(xiàn)程并沒(méi)有實(shí)質(zhì)上的區(qū)別。 可以同時(shí)啟動(dòng)多個(gè)Engine實(shí)例,每個(gè)Engine對(duì)應(yīng)一個(gè)Platform Runner,每個(gè)Runner跑在各自的線(xiàn)程里。這也是Fuchsia(Google正在開(kāi)發(fā)的操作引擎)里Content Handler的工作原理。一般情況下,一個(gè)Flutter應(yīng)用啟動(dòng)的時(shí)候會(huì)創(chuàng)建一個(gè)Engine實(shí)例,Engine創(chuàng)建的時(shí)候會(huì)創(chuàng)建一個(gè)線(xiàn)程供Platform Runner使用。
跟Flutter Engine的所有交互(接口調(diào)用)必須發(fā)生在Platform Thread,試圖在其它線(xiàn)程中調(diào)用Flutter Engine會(huì)導(dǎo)致無(wú)法預(yù)期的異常。這跟Android和IOS對(duì)于UI的操作都必須在主線(xiàn)程進(jìn)行相類(lèi)似。需要注意的是在Flutter Engine中有很多模塊都是非線(xiàn)程安全的。一旦引擎正常啟動(dòng)運(yùn)行起來(lái),所有引擎API調(diào)用都將在Platform Thread里發(fā)生。
Platform Runner所在的Thread不僅僅處理與Engine交互,它還處理來(lái)自平臺(tái)的消息。這樣的處理比較方便的,因?yàn)閹缀跛幸娴恼{(diào)用都只有在Platform Thread進(jìn)行才能是安全的,Native Plugins不必要做額外的線(xiàn)程操作就可以保證操作能夠在Platform Thread進(jìn)行。如果Plugin自己?jiǎn)?dòng)了額外的線(xiàn)程,那么它需要負(fù)責(zé)將返回結(jié)果派發(fā)回Platform Thread以便Dart能夠安全地處理。規(guī)則很簡(jiǎn)單,對(duì)于Flutter Engine的接口調(diào)用都需保證在Platform Thread進(jìn)行。
阻塞Platform Thread不會(huì)直接導(dǎo)致Flutter應(yīng)用的卡頓(跟iOS android主線(xiàn)程不同)。盡管如此,平臺(tái)對(duì)Platform Thread還是有強(qiáng)制執(zhí)行限制。所以建議復(fù)雜計(jì)算邏輯操作不要放在Platform Thread而是放在其它線(xiàn)程(不包括我們現(xiàn)在討論的這個(gè)四個(gè)線(xiàn)程)。其他線(xiàn)程處理完畢后將結(jié)果轉(zhuǎn)發(fā)回Platform Thread。長(zhǎng)時(shí)間卡住Platform Thread應(yīng)用有可能會(huì)被系統(tǒng)Watchdot強(qiáng)行殺死。
Flutter Engine用于執(zhí)行Dart root isolate代碼。Root isolate比較特殊,它綁定了不少Flutter需要的函數(shù)方法。Root isolate運(yùn)行應(yīng)用的main code。引擎啟動(dòng)的時(shí)候?yàn)槠湓黾恿吮匾慕壎?,使其具備調(diào)度提交渲染幀的能力。
對(duì)于每一幀,引擎要做的事情有:
Root isolate通知Flutter Engine有幀需要渲染。
Flutter Engine通知平臺(tái),需要在下一個(gè)vsync的時(shí)候得到通知。
平臺(tái)等待下一個(gè)vsync
對(duì)創(chuàng)建的對(duì)象和Widgets進(jìn)行Layout并生成一個(gè)Layer Tree,Layer Tree馬上被提交給Flutter Engine。當(dāng)前階段沒(méi)有進(jìn)行任何光柵化,這個(gè)步驟僅是生成了對(duì)需要繪制內(nèi)容的描述。
創(chuàng)建或者更新Tree,這個(gè)Tree包含了用于屏幕上顯示W(wǎng)idgets的語(yǔ)義信息。這個(gè)東西主要用于平臺(tái)相關(guān)的輔助Accessibility元素的配置和渲染。
除了渲染相關(guān)邏輯之外Root Isolate還是處理來(lái)自Native Plugins的消息響應(yīng),Timers,MicroTasks和異步IO。
Root Isolate負(fù)責(zé)創(chuàng)建管理的Layer Tree最終決定什么內(nèi)容要繪制到屏幕上。因此這個(gè)線(xiàn)程的過(guò)載會(huì)直接導(dǎo)致卡頓掉幀。
如果確實(shí)有無(wú)法避免的繁重計(jì)算,建議將其放到獨(dú)立的Isolate去執(zhí)行,比如使用compute關(guān)鍵字或者放到非Root Isolate,這樣可以避免應(yīng)用UI卡頓。但是需要注意的是非Root Isolate缺少Flutter引擎需要的一些函數(shù)綁定,你無(wú)法在這個(gè)Isolate直接與Flutter Engine交互。所以只在需要大量計(jì)算的時(shí)候采用獨(dú)立Isolate。
用于執(zhí)行設(shè)備GPU的相關(guān)調(diào)用。UI Task Runner創(chuàng)建的Layer Tree信息是平臺(tái)不相關(guān),也就是說(shuō)Layer Tree提供了繪制所需要的信息,具體如何實(shí)現(xiàn)繪制取決于具體平臺(tái)和方式,可以是OpenGL,Vulkan,軟件繪制或者其他Skia配置的繪圖實(shí)現(xiàn)。GPU Task Runner中的模塊負(fù)責(zé)將Layer Tree提供的信息轉(zhuǎn)化為實(shí)際的GPU指令。GPU Task Runner同時(shí)也負(fù)責(zé)配置管理每一幀繪制所需要的GPU資源,這包括平臺(tái)Framebuffer的創(chuàng)建,Surface生命周期管理,保證Texture和Buffers在繪制的時(shí)候是可用的。
基于Layer Tree的處理時(shí)長(zhǎng)和GPU幀顯示到屏幕的耗時(shí),GPU Task Runner可能會(huì)延遲下一幀在UI Task Runner的調(diào)度。一般來(lái)說(shuō)UI Runner和GPU Runner跑在不同的線(xiàn)程。存在這種可能,UI Runner在已經(jīng)準(zhǔn)備好了下一幀的情況下,GPU Runner卻還正在向GPU提交上一幀。這種延遲調(diào)度機(jī)制確保不讓UI Runner分配過(guò)多的任務(wù)給GPU Runner。
GPU Runner可以導(dǎo)致UI Runner的幀調(diào)度的延遲,GPU Runner的過(guò)載會(huì)導(dǎo)致Flutter應(yīng)用的卡頓。一般來(lái)說(shuō)用戶(hù)沒(méi)有機(jī)會(huì)向GPU Runner直接提交任務(wù),因?yàn)槠脚_(tái)和Dart代碼都無(wú)法跑進(jìn)GPU Runner。但是Embeder還是可以向GPU Runner提交任務(wù)的。因此建議為每一個(gè)Engine實(shí)例都新建一個(gè)專(zhuān)用的GPU Runner線(xiàn)程。
主要功能是從圖片存儲(chǔ)(比如磁盤(pán))中讀取壓縮的圖片格式,將圖片數(shù)據(jù)進(jìn)行處理為GPU Runner的渲染做好準(zhǔn)備。在Texture的準(zhǔn)備過(guò)程中,IO Runner首先要讀取壓縮的圖片二進(jìn)制數(shù)據(jù)(比如PNG,JPEG),將其解壓轉(zhuǎn)換成GPU能夠處理的格式然后將數(shù)據(jù)上傳到GPU。這些復(fù)雜操作如果跑在GPU線(xiàn)程的話(huà)會(huì)導(dǎo)致Flutter應(yīng)用UI卡頓。但是只有GPU Runner能夠訪(fǎng)問(wèn)GPU,所以IO Runner模塊在引擎啟動(dòng)的時(shí)候配置了一個(gè)特殊的Context,這個(gè)Context跟GPU Runner使用的Context在同一個(gè)ShareGroup。事實(shí)上圖片數(shù)據(jù)的讀取和解壓是可以放到一個(gè)線(xiàn)程池里面去做的,但是這個(gè)Context的訪(fǎng)問(wèn)只能在特定線(xiàn)程才能保證安全。這也是為什么需要有一個(gè)專(zhuān)門(mén)的Runner來(lái)處理IO任務(wù)的原因。獲取諸如ui.Image這樣的資源只有通過(guò)async call,當(dāng)這個(gè)調(diào)用發(fā)生的時(shí)候Flutter Framework告訴IO Runner進(jìn)行剛剛提到的那些圖片異步操作。這樣GPU Runner可以使用IO Runner準(zhǔn)備好的圖片數(shù)據(jù)而不用進(jìn)行額外的操作。
用戶(hù)操作,無(wú)論是Dart Code還是Native Plugins都是沒(méi)有辦法直接訪(fǎng)問(wèn)IO Runner。盡管Embeder可以將一些一般復(fù)雜任務(wù)調(diào)度到IO Runner,這不會(huì)直接導(dǎo)致Flutter應(yīng)用卡頓,但是可能會(huì)導(dǎo)致圖片和其它一些資源加載的延遲間接影響性能。所以建議為IO Runner創(chuàng)建一個(gè)專(zhuān)用的線(xiàn)程
android & iOS平臺(tái)上面每一個(gè)Engine實(shí)例啟動(dòng)的時(shí)候會(huì)為UI,GPU,IO Runner各自創(chuàng)建一個(gè)新的線(xiàn)程。所有Engine實(shí)例共享同一個(gè)Platform Runner線(xiàn)程
image
An isolated Dart execution context
isolate是Dart對(duì)actor并發(fā)模式的實(shí)現(xiàn)。運(yùn)行中的Dart程序由一個(gè)或多個(gè)actor組成,actor也就是Dart概念里面的isolate。isolate是隔離的,每個(gè)isolate有自己的內(nèi)存和單線(xiàn)程運(yùn)行的實(shí)體. isolate之間不互相共享內(nèi)存,且獨(dú)立GC。
isolate中的代碼是順序執(zhí)行的,且是單線(xiàn)程,所以不存在資源競(jìng)爭(zhēng)和變量狀態(tài)同步的問(wèn)題,也就不需要鎖。Dart中的并發(fā)都是多個(gè)isolate并行實(shí)現(xiàn)的
由于isolate不共享內(nèi)存,所以isolate之間不能直接互相通信,只能通過(guò)Port進(jìn)行通信,而且是異步的
Dart的Isolate是Dart虛擬機(jī)自己管理的,F(xiàn)lutter Engine無(wú)法直接訪(fǎng)問(wèn)。Root Isolate通過(guò)Dart的C++調(diào)用能力把UI渲染相關(guān)的任務(wù)提交到UI Runner執(zhí)行, 這樣就可以跟Flutter Engine相關(guān)模塊進(jìn)行交互,F(xiàn)lutter UI相關(guān)的任務(wù)也被提交到UI Runner也可以相應(yīng)的給Isolate一些事件通知,UI Runner同時(shí)也處理來(lái)自App方面Native Plugin的任務(wù)。 Dart isolate跟Flutter Runner是相互獨(dú)立的,它們通過(guò)任務(wù)調(diào)度機(jī)制相互協(xié)作。
Dart VM將內(nèi)存管理分為新生代(New Generation)和老年代(Old Generation)
新生代:初次分配的對(duì)象都位于新生代中,該區(qū)域主要是存放內(nèi)存較小并且生命周期較短的對(duì)象,比如局部變量。新生代會(huì)頻繁執(zhí)行內(nèi)存回收(GC),回收采用“復(fù)制-清除”算法,將內(nèi)存分為兩塊,運(yùn)行時(shí)每次只使用其中的一塊,另一塊備用。當(dāng)發(fā)生GC時(shí),將當(dāng)前使用的內(nèi)存塊中存活的對(duì)象拷貝到備用內(nèi)存塊中,然后清除當(dāng)前使用內(nèi)存塊,最后,交換兩塊內(nèi)存的角色。
老年代: 在新生代的GC中“幸存”下來(lái)的對(duì)象,它們會(huì)被轉(zhuǎn)移到老年代中。老年代存放生命力周期較長(zhǎng),內(nèi)存較大的對(duì)象。老年代的GC回收采用“標(biāo)記-清除”算法,分成標(biāo)記和清除兩個(gè)階段。在標(biāo)記階段會(huì)觸發(fā)停頓,多線(xiàn)程并發(fā)的完成對(duì)垃圾對(duì)象的標(biāo)記,降低標(biāo)記階段耗時(shí)。在清理階段,由GC線(xiàn)程負(fù)責(zé)清理回收對(duì)象,和應(yīng)用線(xiàn)程同時(shí)執(zhí)行,不影響應(yīng)用運(yùn)行。
Android將中內(nèi)存分java內(nèi)存或native內(nèi)存,通常在代碼中的申請(qǐng)的內(nèi)存都在這兩個(gè)范圍內(nèi)
java內(nèi)存是指java或kotlin分配的內(nèi)存對(duì)象
native內(nèi)存是指由C/C++中分配的內(nèi)存,也包括一些android原生系統(tǒng)占用的內(nèi)存,如圖像資源和其他圖形等
Flutter中的image占用的不用這兩種內(nèi)存,而是Graphics內(nèi)存,Graphics內(nèi)存內(nèi)存是指圖形緩沖區(qū)隊(duì)列向屏幕顯示像素所使用的內(nèi)存,圖形緩沖區(qū)是指GL表面,GL紋理等。Graphics內(nèi)存是與CPU共享的內(nèi)存,而不是GPU專(zhuān)用的內(nèi)存
Flutter常見(jiàn)的種運(yùn)行模式:Debug,Release和Profile
Release和Profile模式比較類(lèi)似,不用之處在于Profile模式的服務(wù)擴(kuò)展的支持,支持跟蹤,以及最小化使用跟蹤信息需要的依賴(lài)。Profile并不支持模擬器,原因在于模擬器上的診斷并不代表真實(shí)的性能。所有重點(diǎn)截介紹
Debug和Release的差異
Debug模式:使用JIT編譯,支持模擬器和設(shè)備。打開(kāi)了斷言支持,包括所有的調(diào)試信息,服務(wù)擴(kuò)展和Observatory等調(diào)試輔助。此模式為快速開(kāi)發(fā)和運(yùn)行做了優(yōu)化,但并未對(duì)執(zhí)行速度,包大小和部署做優(yōu)化。
所以能實(shí)現(xiàn)秒級(jí)別的hot reload
Release模式:使用AOT編譯,只支持真機(jī),不支持模擬器。關(guān)閉了所有斷言,盡可能多地去掉了調(diào)試信息,關(guān)閉了所有調(diào)試工具。為快速啟動(dòng),快速執(zhí)行,包大小做了優(yōu)化。禁止了所有調(diào)試輔助手段,服務(wù)擴(kuò)展。
Platform Channel用來(lái)實(shí)現(xiàn)flutter和Native之間的通訊,實(shí)現(xiàn)方式類(lèi)似遠(yuǎn)程通訊。
Flutter定義了三種Channel:
BasicMessageChannel:用于傳遞字符串和半結(jié)構(gòu)化的信息
MethodChannel:用于傳遞方法調(diào)用(method invocation)
EventChannel: 用于數(shù)據(jù)流(event streams)的通信
這三種channel的工作原理都一致,都用三個(gè)基本的屬性:
name: String類(lèi)型,代表Channel的名字,也是其唯一標(biāo)識(shí)符
Messager:BinaryMessenger類(lèi)型,代表消息信使,是消息的發(fā)送與接收的工具
codec: MessageCodec類(lèi)型或MethodCodec類(lèi)型,代表消息的編解碼器
BinaryMessenger是Native端與Flutter端通信的工具,其通信使用的消息格式為二進(jìn)制格式數(shù)據(jù)。初始化一個(gè)Channel,并向該Channel注冊(cè)處理消息的Handler時(shí),實(shí)際上會(huì)生成一個(gè)與之對(duì)應(yīng)的BinaryMessageHandler,并以channel name為key,注冊(cè)到BinaryMessenger中。當(dāng)Flutter端發(fā)送消息到BinaryMessenger時(shí),BinaryMessenger會(huì)根據(jù)其入?yún)hannel找到對(duì)應(yīng)的BinaryMessageHandler,并交由其處理。
BinaryMessenger只和BinaryMessageHandler通訊。而Channel和BinaryMessageHandler則是一一對(duì)應(yīng)的。由于Channel從BinaryMessageHandler接收到的消息是二進(jìn)制格式數(shù)據(jù),無(wú)法直接使用,故Channel會(huì)將該二進(jìn)制消息通過(guò)Codec(消息編解碼器)解碼為能識(shí)別的消息并傳遞給Handler進(jìn)行處理。
當(dāng)Handler處理完消息之后,會(huì)通過(guò)回調(diào)函數(shù)返回result,并將result通過(guò)編解碼器編碼為二進(jìn)制格式數(shù)據(jù),通過(guò)BinaryMessenger發(fā)送回Flutter端。
Codec:息編解碼器,主要用來(lái)將二進(jìn)制格式的數(shù)據(jù)轉(zhuǎn)化為Handler能夠識(shí)別的數(shù)據(jù),F(xiàn)lutter定義了兩種Codec:MessageCodec和MethodCodec
MessageCodec用于二進(jìn)制格式數(shù)據(jù)與基礎(chǔ)數(shù)據(jù)之間的編碼和解碼。有多重實(shí)現(xiàn)如:BinaryCodec, StringCodec, JSONMessageCodec等
MethodCodec用于二進(jìn)制數(shù)據(jù)與方法調(diào)用(MethodCall)和返回結(jié)果之間的編解碼。MethodChannel和EventChannel所使用的編解碼器均為MethodCodec。
MethodCodec用于MethodCall對(duì)象的編解碼,一個(gè)MethodCall對(duì)象代表一次從Flutter端發(fā)起的方法調(diào)用。MethodCall有2個(gè)成員變量:String類(lèi)型的method代表需要調(diào)用的方法名稱(chēng),通用類(lèi)型(Android中為Object,iOS中為id)的arguments代表需要調(diào)用的方法入?yún)ⅰ?/p>
由于處理的是方法調(diào)用,MethodCodec多了對(duì)調(diào)用結(jié)果的處理。當(dāng)方法調(diào)用成功時(shí),使用encodeSuccessEnvelope將result編碼為二進(jìn)制數(shù)據(jù),而當(dāng)方法調(diào)用失敗時(shí),則使用encodeErrorEnvelope將error的code、message、detail編碼為二進(jìn)制數(shù)據(jù)。
MethodCodec有兩種實(shí)現(xiàn):JSONMethodCodec和StandardMethodCodec
由于Platform Channel運(yùn)行在flutter App的UI Task Runner, 對(duì)應(yīng)的native實(shí)現(xiàn)運(yùn)行在Platform Task Runner,而Platform Task Runner運(yùn)行在主線(xiàn)程,所以在native實(shí)現(xiàn)是不能進(jìn)行耗時(shí)的操作,且Platform Task Runner是非線(xiàn)程安全的,所以要保證回調(diào)函數(shù)在主線(xiàn)程中執(zhí)行
Platform Channel支持大數(shù)據(jù)傳遞,傳遞大內(nèi)存數(shù)據(jù)塊時(shí),使用BasicMessageChannel以及BinaryCodec。而整個(gè)數(shù)據(jù)傳遞的過(guò)程中,唯一可能出現(xiàn)數(shù)據(jù)拷貝的位置為native二進(jìn)制數(shù)據(jù)轉(zhuǎn)化為Dart語(yǔ)言二進(jìn)制數(shù)據(jù)。若二進(jìn)制數(shù)據(jù)大于閾值時(shí)(目前閾值為1000byte)則不會(huì)拷貝數(shù)據(jù),直接轉(zhuǎn)化,否則拷貝一份再轉(zhuǎn)化。
感謝各位的閱讀!關(guān)于“flutter是什么”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。