2018-04-11

LaunchMode & Intent Flag?&?TaskAffinity

LaunchMode

launchMode分為四種:?

standard

  standard啟動模式為最基本的啟動模式,默認為該種啟動模式,特點就是每當發(fā)送一個intent請求打開該activity時,都會創(chuàng)建一個新的activity實例。實際使用情況分為兩種,一種是本應(yīng)用打開,一種是跨應(yīng)用打開:

本應(yīng)用打開,新創(chuàng)建的activity實例放入本應(yīng)用,即發(fā)送intent的task棧的頂部,這個比較簡單

跨引用打開,這里有一個需要注意的地方是跨應(yīng)用打開的時候會在 Recent app 頁面顯示兩個獨立項,但是此時它們兩個 Activity 仍然是在一個棧中,非常感謝@夢想編制楠灬 的指正,跨應(yīng)用打開在 Standard 模式下也是在一個棧中,雖然在 Recent app 頁面是兩個頁面:?


但是問題來了,又一次我偶然發(fā)現(xiàn)使用瀏覽器打開手機上的bilibili則是在同一個 Recent App 項中:?


使用命令adb shell dumpsys activity獲取手機的的activity棧的詳細信息


如上圖所示,com.htc.sense.browser/.BrowserActivity和tv.danmaku.bili/.ui.video.VideoDetailsActivity在同一個 recent app 頁面中,這是怎么回事了,最后我發(fā)現(xiàn)有一個intent的flag變量有該作用:FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,只要將該flag設(shè)置進intent中就會將跨應(yīng)用的activity打開在同一個 Recent app 中,感興趣的可以試一下。

singleTop


singleTop其實和standard幾乎一樣,和standard算一組,使用singleTop的Activity也可以創(chuàng)建很多個實例。唯一不同的就是,如果調(diào)用的目標Activity已經(jīng)位于調(diào)用者的Task的棧頂,則不創(chuàng)建新實例,而是使用當前的這個Activity實例,并調(diào)用這個實例的onNewIntent方法。?

這個使用場景比較少,可以使用的例子比如用戶已經(jīng)在當前activity,用戶點擊一條推送消息之后也需要跳轉(zhuǎn)到當前activity,那么為了避免activity的重復(fù)打開,則需要將該activity設(shè)置為singleTop并且復(fù)寫onNewIntent即可。?

如果是外部程序啟動singleTop的Activity,表現(xiàn)都和standard一樣。

singleTask

使用singleTask啟動模式的Activity?在系統(tǒng)中?只會存在一個實例。如果這個實例已經(jīng)存在,intent就會通過onNewIntent傳遞到這個Activity,并且將棧中該activity之上的activity清除(銷毀過程會調(diào)用Activity生命周期回調(diào)),如果不存在新的Activity實例將被創(chuàng)建。?


 實際使用情況也分為兩組:

本應(yīng)用啟動,在一個應(yīng)用中啟動設(shè)置為singleTask的activity,如果該activity在task棧中不存在,則會創(chuàng)建一個新的實例放在棧頂,如果在activity的task棧中已經(jīng)存在了該activity實例,則會將棧中該activity實例之上的其他activity實例清空,并且會調(diào)用該activity的onNewIntent方法。最常用的使用例子就是首頁,比如首頁上面已經(jīng)有了很多的activity,回到首頁就可以使用這種方式,然后復(fù)寫首頁的onNewIntent方法。使用提示:onNewIntent方法中不能進行fragment的相關(guān)操作http://blog.sina.com.cn/s/blog_5da93c8f0101rgb2.html

跨應(yīng)用啟動,由于整個系統(tǒng)只能存在activity的一個實例,所以如果系統(tǒng)中不存在該activity,則會啟動一個新的task去啟動該activity,并且將該activity放入棧底。如果系統(tǒng)中存在該activity實例,則會直接啟動該activity,調(diào)用該activity的onNewIntent的方法,同時將該activity task棧上面的其他activity清空(銷毀過程會調(diào)用Activity生命周期回調(diào)),此時如果用戶摁下返回鍵,那么將在singleTask activity的task棧中操作,即返回該棧中singleTask activity的上一個activity直到該棧中無activity時才會返回到最開始啟動singleTask activity的activity中。還有一種情況是singleTask Activity所在的應(yīng)用進程存在,但是singleTask Activity實例不存在,那么從別的應(yīng)用啟動這個Activity,新的Activity實例會被創(chuàng)建,并放入到所屬進程所在的Task中,并位于棧頂位置。

注意如果使用了singleTask,FLAG_ACTIVITY_RESET_TASK_IF_NEEDED這個flag將會失效。?

需要特別注意的是:?

1.在4.x和之前的系統(tǒng)下,A1(startActivityForResult)->A2(singleTask, startActivityForResult)->A3->A4,當A1打開A2之后會立即回調(diào)onActivityResult()函數(shù),A2打開A3仍然可以正?;卣{(diào)onActivityResult();但是從5.0開始,A1打開A2的時候 onActivityResult() 函數(shù)也能正常的回調(diào),不會立即回調(diào)。?

2.在4.x和之前的系統(tǒng)下,A1(startActivityForResult)->A2(singleTask, startActivityForResult)->A3,生命周期的流程是

(注:onCreate和onDestroy這兩個生命周期沒有變化,所以沒有加進去,還有一個是A1.onStop生命周期在A2.onResume之后這個是不一定的,視情況而定),上面的變化必須要是startActivityForResult()+5.0之前的系統(tǒng)才會出現(xiàn),可以推測是由于onActivityResult()函數(shù)引起的這個問題。

singleInstance

和singleTask類似,在系統(tǒng)中?只會存在一個實例,唯一的區(qū)別就是系統(tǒng)不會在singleInstance activity的task棧中啟動任何其他的activity,singleInstance activity棧中僅僅只能有該activity的實例,其他任何從這個activity啟動的activity都會在其他的棧中被打開。?

雖然使用adb shell dumpsys activity可以看到singleInstance activity在一個獨立的task中,但是在任務(wù)管理器中,還是顯示的一個?


需要特別注意的是:?

1.A1->A2(SingleInstance),摁下 Home 鍵之后,點擊應(yīng)用圖標再次進入應(yīng)用,返回的是 A1 頁面,這是因為 A2 在另一個單獨的 Activity task 棧中,點擊圖標返回的是主 Activity 棧,所以此時顯示的 A1 頁面,而不是 A2 頁面。?

2.注意singleInstance的返回鍵的處理和上面3個 mode 有區(qū)別,如果是使用正常的 startActivity 進行的啟動,啟動順序A1->A2->A3(singleInstance)->A4,在A4頁面摁下back鍵,返回的是A2,再返回A1,接著再次摁下back鍵,返回的才是A3;如果是使用 startActivityForResult 啟動的,在4.x和之前的系統(tǒng)下,表現(xiàn)和之前是一樣的,但是在5.0開始,A1->A2-A3(singleInstance + startActivityForResult)->A4,在A4摁下返回鍵,返回的是A3->A2->A1,這個需要著重說明一下。?

3.另一個比較重要的是,在4.x和之前的系統(tǒng)下,A1(startActivityForResult)->A2(singleInstance, startActivityForResult)->A3->A4,當A1打開A2之后會立即回調(diào)onActivityResult()函數(shù),A2打開A3也會立即回調(diào)onActivityResult()函數(shù);但是從5.0開始,A1打開A2和A2打開A3的兩種情況下 onActivityResult() 函數(shù)都能正常的回調(diào),不會立即回調(diào)。?

4.還有一個比較重要的是,在4.x和之前的系統(tǒng)下,A1(startActivityForResult)->A2(singleInstance, startActivityForResult)->A3,生命周期的流程是

和singleTask一樣,也是必須要是startActivityForResult()+5.0之前的系統(tǒng)才會出現(xiàn),區(qū)別就只是A2打開A3的情況不同。

Intent Flag

  Intent的flag有很多,介紹一下吧

FLAG_ACTIVITY_BROUGHT_TO_FRONT?

比方說我現(xiàn)在有A,在A中啟動B,在A中Intent中加上這個標記。此時B就是以FLAG_ACTIVITY_BROUGHT_TO_FRONT 這個啟動的,在B中再啟動C,D(正常啟動C,D),如果這個時候在D中再啟動B,這個時候最后的棧的情況是 A,C,D,B.。?

FLAG_ACTIVITY_CLEAR_TASK?

如果在調(diào)用startActivity時傳遞這個標記,該task棧中的其他activity會先被清空,然后該activity在該task中啟動,也就是說,這個新啟動的activity變?yōu)榱诉@個空task的根activity。所有老的activity都結(jié)束掉。該標志必須和FLAG_ACTIVITY_NEW_TASK一起使用。?

FLAG_ACTIVITY_CLEAR_TOP?

如果該activity已經(jīng)在task中存在,并且設(shè)置了該task,系統(tǒng)不會啟動新的 Activity 實例,會將task棧里該Activity之上的所有Activity一律結(jié)束掉,然后將Intent發(fā)給這個已存在的Activity。Activity收到 Intent之后,或者在onNewIntent()里做下一步的處理,或者自行結(jié)束然后重新創(chuàng)建自己。如果 Activity 在 AndroidMainifest.xml 里將啟動模式設(shè)置成默認standard模式,并且 Intent 里也沒有設(shè)置 FLAG_ACTIVITY_SINGLE_TOP,那么他將會結(jié)束并且重啟;否則則會傳遞到onNewIntent方法,F(xiàn)LAG_ACTIVITY_CLEAR_TOP 還可以和 FLAG_ACTIVITY_NEW_TASK 配合使用,用來啟動一個task棧的根activity,他將會把該棧清空為根狀態(tài),比如從notification manager啟動activity。?

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET?

已經(jīng)廢棄,請使用FLAG_ACTIVITY_NEW_DOCUMENT?

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS?

設(shè)置完之后,新的activity將不會添加到當前activity列表中,當某些情況下我們不希望用戶通過歷史列表回到我們的Activity的時候這個標記比較有用。他等同于在XML中指定Activity的屬性android:excludeFromRecents=”true”。?

FLAG_ACTIVITY_FORWARD_RESULT?

如果設(shè)置,并且這個Intent用于從一個存在的Activity啟動一個新的Activity,那么,這個作為答復(fù)目標的Activity將會傳到這個新的Activity中。這種方式下,新的Activity可以調(diào)用setResult(int),并且這個結(jié)果值將發(fā)送給那個作為答復(fù)目標的Activity。?

FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY?

一般由系統(tǒng)調(diào)用,比如長摁home鍵從歷史記錄中啟動。?

FLAG_ACTIVITY_MULTIPLE_TASK?

這個標識用來創(chuàng)建一個新的task棧,并且在里面啟動新的activity(所有情況,不管系統(tǒng)中存在不存在該activity實例),經(jīng)常和FLAG_ACTIVITY_NEW_DOCUMENT或者FLAG_ACTIVITY_NEW_TASK一起使用。這上面兩種使用場景下,如果沒有帶上FLAG_ACTIVITY_MULTIPLE_TASK標識,他們都會使系統(tǒng)搜索存在的task棧,去尋找匹配intent的一個activity,如果沒有找到就會去新建一個task棧;但是當和FLAG_ACTIVITY_MULTIPLE_TASK一起使用的時候,這兩種場景都會跳過搜索這步操作無條件的創(chuàng)建一個新的task。和FLAG_ACTIVITY_NEW_TASK一起使用需要注意,盡量不要使用該組合除非你完成了自己的頂部應(yīng)用啟動器,他們的組合使用會禁用已經(jīng)存在的task?;氐角芭_的功能。?

FLAG_ACTIVITY_NEW_DOCUMENT?

api 21之后加入的一個標識,用來在intent啟動的activity的task棧中打開一個document,和documentLaunchMode效果相等,有著不同的documents的activity的多個實例,將會出現(xiàn)在最近的task列表中。單獨使用效果和documentLaunchMode=”intoExisting”一樣,如果和FLAG_ACTIVITY_MULTIPLE_TASK一起使用效果就等同于documentLaunchMode=”always”。?

FLAG_ACTIVITY_NEW_TASK?

設(shè)置此狀態(tài),記住以下原則,首先會查找是否存在和被啟動的Activity具有相同的親和性的任務(wù)棧(即taskAffinity,注意同一個應(yīng)用程序中的activity的親和性在沒有修改的情況下是一樣的,所以下面的a情況會在同一個棧中),如果有,剛直接把這個棧整體移動到前臺,并保持棧中的狀態(tài)不變,即棧中的activity順序不變,如果沒有,則新建一個棧來存放被啟動的activity。?

a. 前提: Activity A和Activity B在同一個應(yīng)用中。?

操作: Activity A啟動開僻Task堆棧(堆棧狀態(tài):A),在Activity A中啟動Activity B, 啟動Activity B的Intent的Flag設(shè)為FLAG_ACTIVITY_NEW_TASK,Activity B被壓入Activity A所在堆棧(堆棧狀態(tài):AB)。?

原因: 默認情況下同一個應(yīng)用中的所有Activity擁有相同的關(guān)系(taskAffinity)。?

b. 前提: Activity A在名稱為”TaskOne應(yīng)用”的應(yīng)用中, Activity C和Activity D在名稱為”TaskTwo應(yīng)用”的應(yīng)用中。

操作1:在Launcher中單擊“TaskOne應(yīng)用”圖標,Activity A啟動開僻Task堆棧,命名為TaskA(TaskA堆棧狀態(tài): A),在Activity A中啟動Activity C, 啟動Activity C的Intent的Flag設(shè)為FLAG_ACTIVITY_NEW_TASK,Android系統(tǒng)會為Activity C開僻一個新的Task,命名為TaskB(TaskB堆棧狀態(tài): C), 長按Home鍵,選擇TaskA,Activity A回到前臺, 再次啟動Activity C(兩種情況:1.從桌面啟動;2.從Activity A啟動,兩種情況一樣), 這時TaskB回到前臺, Activity C顯示,供用戶使用, 即:包含F(xiàn)LAG_ACTIVITY_NEW_TASK的Intent啟動Activity的Task正在運行,則不會為該Activity創(chuàng)建新的Task,而是將原有的Task返回到前臺顯示。

操作2:在Launcher中單擊”TaskOne應(yīng)用”圖標,Activity A啟動開僻Task堆棧,命名為TaskA(TaskA堆棧狀態(tài): A),在Activity A中啟動Activity C,啟動Activity C的Intent的Flag設(shè)為FLAG_ACTIVITY_NEW_TASK,Android系統(tǒng)會為Activity C開僻一個新的Task,命名為TaskB(TaskB堆棧狀態(tài): C), 在Activity C中啟動Activity D(TaskB的狀態(tài): CD) 長按Home鍵, 選擇TaskA,Activity A回到前臺, 再次啟動Activity C(從桌面或者ActivityA啟動,也是一樣的),這時TaskB回到前臺, Activity D顯示,供用戶使用。說明了在此種情況下設(shè)置FLAG_ACTIVITY_NEW_TASK后,會先查找是不是有Activity C存在的棧,根據(jù)親和性(taskAffinity),如果有,剛直接把這個棧整體移動到前臺,并保持棧中的狀態(tài)不變,即棧中的順序不變。

FLAG_ACTIVITY_NO_ANIMATION?

禁止activity之間的切換動畫?

FLAG_ACTIVITY_NO_HISTORY?

該Activity將不在stack中保留,用戶一離開它,這個Activity就關(guān)閉了。?

FLAG_ACTIVITY_NO_USER_ACTION?

禁止activity調(diào)用onUserLeaveHint()函。onUserLeaveHint()作為activity周期的一部分,它在activity因為用戶要跳轉(zhuǎn)到別的activity而退到background時使用。比如,在用戶按下Home鍵(用戶的操作),它將被調(diào)用。比如有電話進來(不屬于用戶的操作),它就不會被調(diào)用。注意:通過調(diào)用finish()時該activity銷毀時不會調(diào)用該函數(shù)。?

FLAG_ACTIVITY_PREVIOUS_IS_TOP?

如果給Intent對象設(shè)置了這個標記,這個Intent對象被用于從一個存在的Activity中啟動一個新的Activity,那么新的這個Activity不能用于接受發(fā)送給頂層activity的intent,這個新的activity的前一個activity被作為頂部activity。?

FLAG_ACTIVITY_REORDER_TO_FRONT?

如果在Intent中設(shè)置,并傳遞給Context.startActivity(),這個標志將引發(fā)已經(jīng)運行的Activity移動到歷史stack的頂端。 例如,假設(shè)一個Task由四個Activity組成:A,B,C,D。如果D調(diào)用startActivity()來啟動Activity B,那么,B會移動到歷史stack的頂端,現(xiàn)在的次序變成A,C,D,B。如果FLAG_ACTIVITY_CLEAR_TOP標志也設(shè)置的話,那么這個標志將被覆蓋。?

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED?

這個標記在以下情況下會生效:1.啟動Activity時創(chuàng)建新的task來放置Activity實例;2.已存在的task被放置于前臺。系統(tǒng)會根據(jù)affinity對指定的task進行重置操作,task會壓入某些Activity實例或移除某些Activity實例。我們結(jié)合上面的FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET可以加深理解。?

FLAG_ACTIVITY_RETAIN_IN_RECENTS?

api21加入。?

默認情況下通過FLAG_ACTIVITY_NEW_DOCUMENT啟動的activity在關(guān)閉之后,task中的記錄會相對應(yīng)的刪除。如果為了能夠重新啟動這個activity你想保留它,就可以使用者個flag,最近的記錄將會保留在接口中以便用戶去重新啟動。接受該flag的activity可以使用autoRemoveFromRecents去復(fù)寫這個request或者調(diào)用Activity.finishAndRemoveTask()方法。?

FLAG_ACTIVITY_SINGLE_TOP?

singleTop一樣?

FLAG_ACTIVITY_TASK_ON_HOME?

api11加入。?

把當前新啟動的任務(wù)置于Home任務(wù)之上,也就是按back鍵從這個任務(wù)返回的時候會回到home,即使這個不是他們最后看見的activity,注意這個標記必須和FLAG_ACTIVITY_NEW_TASK一起使用。?

FLAG_DEBUG_LOG_RESOLUTION?

將log置為可用狀態(tài),如果設(shè)置了這個flag,那么在處理這個intent的時候,將會打印相關(guān)創(chuàng)建日志。?

FLAG_EXCLUDE_STOPPED_PACKAGESFLAG_INCLUDE_STOPPED_PACKAGES?

在3.1之后,系統(tǒng)的package manager增加了對處于“stopped state”應(yīng)用的管理,這個stopped和Activity生命周期中的stop狀態(tài)是完全兩碼事,指的是安裝后從來沒有啟動過和被用戶手動強制停止的應(yīng)用,與此同時系統(tǒng)增加了2個Flag:FLAG_INCLUDE_STOPPED_PACKAGES和FLAG_EXCLUDE_STOPPED_PACKAGES ,來標識一個intent是否激活處于“stopped state”的應(yīng)用。當2個Flag都不設(shè)置或者都進行設(shè)置的時候,采用的是FLAG_INCLUDE_STOPPED_PACKAGES的效果。?

FLAG_FROM_BACKGROUND?

用來標識該intent的操作是一個后端的操作而不是一個直接的用戶交互。?

FLAG_GRANT_PERSISTABLE_URI_PERMISSION?

api19添加?

當和FLAG_GRANT_READ_URI_PERMISSION 和/或FLAG_GRANT_WRITE_URI_PERMISSION一起使用時,uri權(quán)限在設(shè)置重啟之后依然存在直到用戶調(diào)用了revokeUriPermission(Uri, int)方法,這個標識僅為可能的存在狀態(tài)提供許可,接受的應(yīng)用必須要調(diào)用takePersistableUriPermission(Uri, int)方法去實際的變?yōu)榇嬖跔顟B(tài)。?

FLAG_GRANT_PREFIX_URI_PERMISSION?

api21加入。?

當和FLAG_GRANT_READ_URI_PERMISSION 和/或FLAG_GRANT_WRITE_URI_PERMISSION一起使用時,uri的許可只用匹配前綴即可(默認為全部匹配)。?

FLAG_GRANT_READ_URI_PERMISSIONFLAG_GRANT_WRITE_URI_PERMISSION?

如果設(shè)置FLAG_GRANT_READ_URI_PERMISSION這個標記,Intent的接受者將會被賦予讀取Intent中URI數(shù)據(jù)的權(quán)限和lipData中的URIs的權(quán)限。當使用于Intent的ClipData時,所有的URIs和data的所有遞歸遍歷或者其他Intent的ClipData數(shù)據(jù)都會被授權(quán)。FLAG_GRANT_WRITE_URI_PERMISSION同F(xiàn)LAG_GRANT_READ_URI_PERMISSION只是相應(yīng)的賦予的是寫權(quán)限。?

一個典型的例子就是郵件程序處理帶有附件的郵件。進入郵件需要使用permission來保護,因為這些是敏感的用戶數(shù)據(jù)。然而,如果有一個指向圖片附件的URI需要傳遞給圖片瀏覽器,那個圖片瀏覽器是不會有訪問附件的權(quán)利的,因為他不可能擁有所有的郵件的訪問權(quán)限。針對這個問題的解決方案就是per-URI permission:當啟動一個activity或者給一個activity返回結(jié)果的時候,呼叫方可以設(shè)置Intent.FLAG_GRANT_READ_URI_PERMISSION和/或Intent.FLAG_GRANT_WRITE_URI_PERMISSION . 這會使接收該intent的activity獲取到進入該Intent指定的URI的權(quán)限,而不論它是否有權(quán)限進入該intent對應(yīng)的content provider。?

FLAG_RECEIVER_FOREGROUND?

api16添加。?

當發(fā)送廣播時,允許其接受者擁有前臺的優(yōu)先級,更短的超時間隔。?

FLAG_RECEIVER_NO_ABORT?

api19添加?

如果這是一個有序廣播,不允許接受者終止這個廣播,它仍然能夠傳遞給下面的接受者。?

FLAG_RECEIVER_REGISTERED_ONLY?

如果設(shè)置了這個flag,當發(fā)送廣播的時,動態(tài)注冊的接受者才會被調(diào)用,在Androidmanifest.xml 里定義的Receiver 是接收不到這樣的Intent 的。?

FLAG_RECEIVER_REPLACE_PENDING?

api8添加。?

如果設(shè)置了的話,ActivityManagerService就會在當前的系統(tǒng)中查看有沒有相同的intent還未被處理,如果有的話,就由當前這個新的intent來替換舊的intent,所以就會出現(xiàn)在發(fā)送一系列的這樣的Intent 之后,中間有些Intent 有可能在你還沒有來得及處理的時候, 就被替代掉了的情況

taskAffinity

每個Activity都有taskAffinity屬性,這個屬性指出了它希望進入的Task。如果一個Activity沒有顯式的指明該 Activity的taskAffinity,那么它的這個屬性就等于Application指明的taskAffinity,如果 Application也沒有指明,那么該taskAffinity的值就等于包名。而Task也有自己的affinity屬性,它的值等于它的根 Activity的taskAffinity的值。?

TaskAffinity屬性主要和SingleTask啟動模式或者allowTaskReparenting屬性配對使用,在其他情況下沒有意義。當TaskAffinity和singleTask啟動模式配對使用的時候,他是具有該模式的Activity的目前任務(wù)棧的名字,待啟動的Activity會運行在名字和TaskAffinity相同的任務(wù)棧中。allowTaskReparenting用于配置是否允許該activity可以更換從屬task,通常情況二者連在一起使用,用于實現(xiàn)把一個應(yīng)用程序的Activity移到另一個應(yīng)用程序的Task中。allowTaskReparenting用來標記Activity能否從啟動的Task移動到taskAffinity指定的Task,默認是繼承至application中的allowTaskReparenting=false,如果為true,則表示可以更換;false表示不可以。?

如果加載某個Activity的intent,F(xiàn)lag被設(shè)置成FLAG_ACTIVITY_NEW_TASK時,它會首先檢查是否存在與自己taskAffinity相同的Task,如果存在,那么它會直接宿主到該Task中,如果不存在則重新創(chuàng)建Task。

引用

http://droidyue.com/blog/2015/08/16/dive-into-android-activity-launchmode/?

http://blog.csdn.net/lygglobetech/article/details/6600692

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容