html
採用最新版本手機 APP(以後稱爲 MyApp)代碼,實現其 Pad 化,爲平板和大屏手機用戶提供更好的體驗。爲實現 MyApp 的 Pad 化工做,須要咱們首先來了解一下 MyApp 項目經典頁面的構成以及 Pad 化後的頁面結構的變化。java
如今主流手機 APP 主頁一般採用標籤欄加標籤內容方式顯示。而經過主頁進入的二級頁面所有采用全屏方式展現。好比手機 QQ,微信,支付寶等等都是採用 Tab 欄方式爲主,進入一個具體功能後,全屏打開。咱們項目也是如此。下面看一下 MyApp 項目手機端的頁面構成圖。android
左側是一個 Tab 欄(區域1)加 Tab Content(區域2)構成的頁面,右側是在 TabContent 中點擊具體功能後進入的一個功能詳情頁面(全屏區域3)。
查看代碼,發現除 TabContent 區域2,從主頁開始到其餘全屏顯示的頁面所有采用 Android Activity 組件實現。經統計得出大概有幾百個 Activity。這些 Activity還包含好比Web進程,peak 進程(圖片選擇查看)等其餘非主進程 Activity。web
瞭解了手機 MyApp 頁面構成後,還要來看 Pad 化後 UI 結構的變化,經過對比來探索 Pad 化最佳的實現方案。下面是咱們的 PAD 版本頁面結構圖。
微信
因爲 Pad 平板的空間要遠大於手機空間,因此,在主頁中 Pad 所展現的內容要比手機更多。經過觀察設計圖發現,整個頁面分爲了3塊區域,與手機端頁面的1,2,3區域一一對應。Tab 欄被移到了左側1區,Tab Content 被移到了中間2區,而在2區打開的 Details 頁面則要求在3區展現,而再也不是像手機 APP 同樣全屏展現。架構
經過了解 MyApp 項目經典頁面構成和 pad 版頁面結構的變化,以及快速Pad 化的原則,咱們開始了對手機 APP pad 化實現方案的漫漫探索。
首先想到的是,既然手機APP頁面主要是由Activity構成,那麼咱們能不能把 Activity 縮小,讓多個 Activity 在同一屏幕顯示呢,很快咱們的方案1出來了。app
方案1,若是把設計圖的整個頁面稱爲主 Activity,主 Activity 全屏顯示不變,在主 Activiy 中打開的新 Activity (稱爲A)縮小顯示在設計圖3區,咱們就能夠實現 Pad 設計的要求。那麼咱們具體實現步驟爲:
1,A類 Activity 繼承 Base Activity
2,修改 Base Activity 的 window 的起始座標x和寬度 width,讓其恰好位於3區。
3,A類 Activity 背景改成透明
4,讓在A類 Activity 繼續打開的 Activity,重複1,2,3,4步驟。 ide
可是很快就發現了問題。模塊化
在當前 Tab 打開 Activity A,切換 Tab 後 A Activity 仍然顯示。工具
每一個 Tab 打開的 Activity,都處於同一個 Activity 棧中,按打開前後順序添加,點擊返回鍵也是順序退出的。這樣每一個 Tab 中打開的Activity 都混在一塊兒了,而不是彼此獨立。致使 back 鍵出現問題。
既然直接顯示 Actvity 有問題,想一想反正都是顯示UI佈局,能不能把 A 類 Activity 的根佈局拉出來掛載在主 Activity 右側?從而咱們推導出了方案2。
方案2:在主 Activity 啓動 A 類 Activity 時,獲取 A 的根佈局,添加到主 Activity 在右側3區預留的一個空佈局中。具體實現步驟爲:
1,重寫主 Activity 的 startActivity 方法。
2,使用 LocalActivityManager 啓動 A 類 Aactivity 返回 window 對象。
3,經過 Window 對象 window.getDecorView()返回打開 Activity 的佈局並 Add 到主 Actvity 上。
4,重寫主 Activity 的 Back 邏輯,在點擊返回鍵時 remove 掉掛載的 decorView。
可是在 Demo 上一測試,就發現了不少問題,
用 mat 查看到 A 類 Activity 是怎麼也釋放不掉的,由於 LocalActivityManager 已經抓住了 A 類 Activity 的 parent。
直接拿出 A 類 Activity 的 decorView,已經讓A類 Activity 喪失了 Activity 的一切特性,包括生命週期,返回邏輯,ActivityResult,以及啓動其餘 Activity 等功能。會致使以前正常運行的A類 Activity 出現大量問題。
既然直接拿到根視圖沒有用,那該怎麼作纔好呢?怎麼作才能使 A 類 Activity 的頁面掛載在主 Activity 右側,又能保證 A 的生命週期和 Activity 行爲呢?通過你們一番思考討論後,能不能利用插件的思想,把 A 類 Activity 中的生命週期方法以及繼承自 Activity 類的方法都拿出來了,在適當時候本身調用呢?這樣就保證了原來 A 中的代碼不會出現問題,不須要修改 A 中的任何代碼。可是用什麼作容器(代理)比較好了?以後咱們想到了用 Fragment,,由於 Fragment 能夠做爲所屬 Activity 的一個塊存在於任何位置,而且 Fragment 有本身的生命週期,並受所屬 Activity 的生命週期影響,它就像一個子 Activity 同樣。簡直是絕佳容器。並且 Fragment 比較輕量,自己由 Activity 來管理(而不像 Activity 由 Android 系統服務管理),在不一樣的佈局結構中重用 Fragment 能夠優化屏幕空間和用戶體驗。
注意,下面所說的把 Activity 轉換爲 Fragment 並非直接把 Activity 變爲 Fragment,這會付出巨大代價,而是以一個空的 Fragment 爲容器來承載 Activity。
終於方案3順利出爐。
方案3,把 Activity 轉換爲 Fragment,使用 Fragment 模擬 Activity 的方法。而後把 Fragment 直接添加到主 Activity 的右側佈局中。實現的具體步驟爲:
1,新增 BasePadActivity,讓全部 Activity 繼承 BasePadActivity,重寫 StartActivity 方法,在該方法中手動 New 出A類 Activity,並把主 Activity 的上下文對象 Context 傳遞給它。
2,建立 MyFragment,持有A類 Activity 實例引用,在 MyFragment 生命週期中直接調用A類 Activity 生命週期方法,並把A類 Activity 的視圖傳遞給 Fragment 使用。
3,A類 Activity 中繼承自 Activity 的方法所有重寫,具體實現由步驟1中的獲得的主 Activity 上下文 context 處理。這樣A類 Activity 已經成爲一個普通實例化對象,再也不由 Android 系統管理。
該方案有較多優勢,因爲繼承 base,不只能迅速將大量 Activity 快換爲 Fragment,並且轉換後,使原來A類 Activity 的功能邏輯維持正常。而且因爲A類 Activity 的上下文其實使用了主 Activity 的上下文對象,須要在A類 Activity 獲取 Resouce,Window,Asset 對象等都能經過主 Activity 的 context 進行獲取。
該方案實現後,最初測試好像一切正常,可是不就後也發現了若干問題:
原 Activity 自定義 TitleBar 出現問題。
每一個 Tab 標籤中打開的 Fragment,因爲都屬於一個主 Activity,致使它們只有一個 Fragment 棧,Back 返回時會出現與方案1相似的問題。
儘管 Activity 轉換爲 Fragment 後,大部分行爲都進行了模擬,可是還有一些重要行爲沒有作處理,好比說 Activity 的啓動模式,Back 鍵,onActivityResult 等等,這些還要進行完善。
對於聲明爲多進程的 Activity,轉換爲 Fragment 後失去了多進程的特性。由於這些 Fragment 屬於主 Activity,主 Activity 是屬於手Q進程的。
該方案雖然也有諸多問題,可是通過調研和測試,發現基本都是能解決的。出於該方案的優勢,以及對其出現的問題的解決難易評估,最終決定在該方案基礎上進行優化和完善。那麼對上述出現的若干問題該如何解決呢?
設置自定義 TitleBar,是 Activity 所提供的接口,查看手機APP代碼,大部分 Activity 都繼承了 TitleBarActivity,經過
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_commen_title);
來定義 TitleBar 的樣式。因此改成 Fragment 以後致使大量 Activity titlebar 顯示不出,甚至 crash。那麼能不能實現一個自定義的 window 對象繼承 android.view.Window,經過 getWindow()獲得的是咱們自定義的 Window 對象,它能夠處理自定義 Titlebar 的使用。
Pad 版本主頁也是分爲多個 Tab 標籤欄的,每一個標籤欄中對 Fragment 的操做應該是相互獨立的。Android中Fragment都是由 FragmentManager 來管理的。Fragment 的添加,替換,移除等操做都是由 FragmentManager 中對象 FragmentTransaction 來記錄和執行。每一個 Activity 中只有一個 FragmentManager 實例,經過代碼
Activity.java
final FragmentManagerImpl mFragments = new FragmentManagerImpl(); public FragmentManager getFragmentManager() { return mFragments; }
獲取。若是把設計圖中的整個頁面稱爲主 Activity,用主 Activity 中一個 FragmentManager 來管理全部標籤欄的 Fragment 顯然會引發混亂,那麼可否實現每一個標籤頁中都有一個 FragmentManager 的實例來管理當前標籤中全部 Activity 轉換的 Fragment?
完善 Fragment 的 Activity 行爲,好比還須要模擬 Activity 的啓動模式、Activity result、startActivity、finish、onBackPressed 等等。
在回答這個問題以前,要先問一個問題,爲何不都轉換爲 Fragment 呢?
以前研究手機 APP 項目代碼發現,許多Activity都是設計成屬於其餘進程,好比 Web 進程。這樣設計的緣由:
其一是這類 Activity 功能都是屬於同一模塊,出現 crash 也不會讓整個QQ崩潰。
另一個重要緣由是,Android 平臺對每一個進程都有內存限制,使用多進程就可使APP所使用的內存加大幾倍。其餘進程能夠分擔主進程的內存壓力,大大下降內存溢出致使的 crash。
因此不能輕易把這些 Activity 轉換爲 Fragment,由於轉換爲 Fragment,就失去了 Activity 多進程的特性,違背了以前設計初衷,大大增長了APP的內存壓力。那麼這種狀況下是否能讓多個 Activity 在同一屏幕顯示,能不能讓從主 Activity 打開的新 Activity 變爲透明,而且讓其大小和位置恰好覆蓋設計圖的區域3,同時讓屬於主 Activity 的區域1,和區域2接收事件。這樣既讓 Acitvity 擁有多進程的特性,又讓他們看起來就像是在同一個 Activity 中操做。咦,這不是咱們的方案1嗎? 對的,因爲以上種種緣由,對於多進程的 Activity,咱們仍是要按照方案1來處理。
那麼如何解決解決方案1中的問題。
在每一個標籤頁打開的多進程 Activity,應該只與本標籤頁有關聯,在切換到其餘標籤後,這些 Activity 應該隱藏起來,從新再切換 Tab 回到該標籤時,以前在該標籤打開的這些 Activity 應該從新顯示。並且每一個 Tab 的 Activitys 都應該有一個 Activity 棧來管理。
這該如何實現呢?經過閱讀http://developer.android.com/guide/components/tasks-and-back-stack.html瞭解到
一個 app 中一般包含若干個 Activitys,咱們能夠把這些 Activity 分爲若干類,讓每一類都屬於同一個 Task,以多任務的方式把這些 Activity 分爲若干組。好比把在 Tab1欄內打開的多進程 Activity 放入一個Task中,把Tab2中打開的多進程 Activity 放入另一個 Task 中,切換 tab 時,只須要讓兩個 task 交替移到前臺顯示或後臺隱藏便可,並且每一個Task中都維護着一個 Activity 棧。該想法彷佛能解決這個問題。
那麼看到這裏你們又會有另一個疑問了?既然能解決方案1中的問題,爲何不直接所有使用方案1呢?還要把Activity轉爲Fragment幹嗎?
1,實現的問題,使用多Task的實現方式,在Android中須要聲明Activity的TaskAffinity,而 TaskAffinity 不能在代碼中動態聲明,而只能寫在配置文件中,致使不一樣Tab打開的同一個Activity可能須要在配置文件中聲明兩次,由於它們的 TaskAffinity 要不同,而同一個Activity是不能聲明兩次的,因此只有寫一個空的 Activity 繼承它,致使大量空Activity產生,並且在代碼中啓動 Activity 前還要重定向到繼承的Activity,比較麻煩。多進程 Activity 畢竟仍是少數,因此能夠這麼作。但所有這樣實現明顯不太可取。
2,體驗的問題,當切換 Tab,把 Task 移入前臺,會有一個延時,並且這個延時並不肯定,致使切回 tab,會先顯示底部的頁面,而後 task 中Activity 才覆蓋上來。
3,機型的問題,極少數機型多是因爲廠家定製的緣由,在多個 Activity 顯示在同一屏幕時會有一個問題,在接收左側主 Activity 的事件時,A類 Activity 會消失。通過緣由查找,發現A類 Activity 的 task 自動回到了後臺。應該是系統源碼被修改了。這樣的話基本無法用了。
通過你們若干分析討論,咱們基本理清楚了方案3所遇到問題的大體解決版本,通過均衡考慮,使用如下解決方案是目前 Pad 化最好的解決方案。
對 MyApp pad 化的整個流程以及會遇到的問題理清楚以後,通過思考和你們的討論肯定了咱們手機端 APP Pad 化的架構方案:
1,轉換 APP 主進程的 Activity 爲 Fragment,轉換過程儘可能不修改原來 Activity 的任何代碼。
2,讓轉換後的 Fragment 模擬 Activity 的行爲,保持 Fragment 和原來 Activity 的行爲一致。
3,使用 LocalActivityManager 實現每一個 Tab 標籤 Fragments 操做的獨立性。
4,多進程 Activity(包括插件 Activity)不轉換爲 Fragment,實現多任務分屏顯示。
實現 BasePadActivity 爲全部 Activity 基類,對 Activity 轉換爲 Fragment 的操做在 BasePadActivity 中實現,利用相似插件的想法,以Fragment爲殼,把真正具體的實現從 Activity 中搬入 Fragment,而不須要修改原 Activity 的任何代碼。經過重寫 StartActivity 方法,讓原來去 startActivity 的動做變爲添加一個新的 Fragment 動做,並調用 addToBackStatck()方法添加到 Fragment 棧中。
下面給出部分僞代碼的實現 ,注意如下代碼都是僞代碼,不少只有方法而無實現, 這裏主要是講思路 。
BasePadActivity.java public class BasePadActivity extends Activity{ /** * 經過重寫startActivityForResult來將Fragment轉換爲Activity */ @Override public void startActivityForResult(Intent intent) { if (isfragment && !isNewProcessActivty()){ //多進程Activity不轉換爲Fragment //初始化activity,注意該Activity是咱們本身實例化出來的 BasePadActivity activity =(BasePadActivity)newInstance(intent); activity.attachBaseContext(getBaseContext()) activity.onCreate(intent.getExtras()); //模擬Activity的onCreate activity.addMyFragment(); } } } public class MyFragment extends Fragment { @Override public View onCreateView() { View contentView = getWindow().getDecorView(); //Fragment的View爲Activity的decorView return contentView; } @Override public void onResume() { super.onResume(); BasePadActivity.this.onResume(); //模擬Activity } @Override public void onPause() { super.onPause(); BasePadActivity.this.onPause(); //模擬Activity onPause } ........ ........ } }
代碼巧妙實現了全部繼承 BasePadActivity 的 Activity 轉換爲Fragment 的過程,固然這裏只展現了轉換一小部分,其餘細節問題並無在代碼中列出來。當打開 Activity 的過程轉換爲打開 Fragment 的過程後,咱們須要讓 Fragment 模擬 Activity 的行爲。
模擬 Activity 的 finish 方法
BasePadActivity.java public void finish() { if (bActivityToFragment) { removeTopFragment(); //移除Fragment棧中最頂層Fragment } }
模擬 Activity 的 onActivityResult,在當前 Fragment 被 finish 去觸發
private void removeTopFragment() { if(popBackStackImmediate()){ //成功把頂層Fragment,從Fragment棧中移出。 handleSetResult(requestCode,false); } } private void handleSetResult(int requestCode){ //觸發上層Fragment的onActivityResult topFragment.onActivityResult(requestCode, resultCode, data); }
模擬 Activity 的返回事件,當把 Activity 轉換爲 Fragment 時,其返回事件已經由該 Fragment 所屬的 Activity 接收,所以須要處理其所屬真正 Activity 的返回事件。經過 FragmentManager 能夠管理該 Activity 中全部 Fragment。
BasePadActivity.java public void onBackPressed() { if(isActivityForFragment()){ //,爲Fragment所屬Activity if(!handleFragmentBackEvent()){ //先處理Fragment自己的返回事件,好比想先關閉當前Fragment菜單。 finishTopFragment(); //最後finish該Fragment } } }
模擬 Activity 的啓動方式,經過獲取 intent.getFlags()值,來判斷 Activity 的啓動模式,經過
public boolean hasFlagClearTop(int flags){ return (flags & Intent.FLAG_ACTIVITY_CLEAR_TOP )!=0 ; } public boolean hasFlagNewTask(int flags){ return (flags & Intent.FLAG_ACTIVITY_NEW_TASK )!=0 ; }
來判斷 Flag 中是否包含相應啓動方式值,來對 Fragment 的打開作相應處理。這裏會稍微麻煩一點,故不做代碼說明了。
在不改變原來 Activity 代碼的狀況下,經過改變 Window 對象,本身實現對 Fragment 佈局的控制。實現自定義 Titlebar。
BasePadActivity.java
public Window getWindow() { if(customWindow==null){ //自定義的window,主要爲了解決不少Activity繼承IphoneTitleBar的問題 customWindow = new Window4FragmentTitle(mContext); } return customWindow; } Window4FragmentTitle.java public class Window4FragmentTitle extends Window{ @Override public void setContentView(View view, LayoutParams params) { if (mContentParent == null) { installDecor(); } mContentParent.addView(view, params); } @Override public void setFeatureInt(int featureId, int value) { if(featureId != FEATURE_CUSTOM_TITLE){ return; } FrameLayout titleContainer = (FrameLayout) findViewById(android.R.id.title); if (titleContainer != null) { mLayoutInflater.inflate(value, titleContainer); } } }
經過 Window4FragmentTitle 調用 setFeatureInt(int)方法,會把自定義的 Title 佈局嵌入到咱們建立的佈局 mDecor 中,而後把 mDecor 放入 Fragment,實現自定義 Titlebar 在 Fragment 中的顯示。
使用 LocalActivityManager 實現標籤佈局,使每一個 Tab 中都有一個 Acitvity 對象,而每一個 Activity 中都會有一個 FragmentManager 對該 Tab 的 Frament 棧進行管理,這樣每一個 Tab 的 Fragments 相互獨立,互不影響。
主Activity
addFrame(Tab1Content.class, mTabs[1]); //Tab1 addFrame(Tab2Content.class, mTabs[2]); //Tab2 ..... public void addFrame(){ mTabHost.setup(getLocalActivityManager()); TabSpec tabSpec = mTabHost.newTabSpec("").setIndicator(tab).setContent(new Intent(this, clz)); mTabHost.addTab(tabSpec); }
經過 setContent(new Intent(this, clz) ,把每一個標籤欄內容以子 Activity 的方式添加進來。
前面說過,對於多進程的 Activity,爲了保持其模塊化以及分擔主進程內存壓力的特色,通過你們討論,不把他們轉換爲 Fragment,那麼就須要解決多個 Activity 一塊兒展現的問題。通過研究,得出的有效實現方式是:讓在每一個標籤欄內打開的 Activity 透明化,而且讓其大小和位置恰好居於設計圖3區,同時能讓處於該 Activity 下方的左側區域的主Activity 接收點擊事件。
1,Activity 透明化實現,在配置文件中聲明 Activity 的 theme 爲透明
2,定義 Activity 的大小和位置。
在 Activity 的 onCreate 方法中實現
WindowManager.LayoutParams layoutParams = window.getAttributes(); layoutParams.gravity = Gravity.RIGHT | Gravity.TOP; //位置居於右側 layoutParams.width = mActivity.getRightPanelWidth(); //寬度爲右側區域寬度
3,讓左側主 Activity 接收事件
經過設置 window 的 WindowManager.LayoutParams 的 flag 爲 FLAG_NOT_TOUCH_MODAL 可讓顯示在透明 Activity 左側下方的主 Activity 接收事件。
新打開的 Activity 位於右區,左區爲主 Activity 顯示區域。左區和右區能同時接收用戶點擊事件,看起來就好像同一個 Activity 同樣。
可是因爲在當前 Tab 打開的位於右區的 Activity,是跟隨當前Tab的,在切換 Tab 後,應該消失,好比 Tab1中打開的 Actvity,切換到Tab2時應該隱藏掉,從新再切換回 Tab1時讓其從新顯示,保留現場。該功能要如何實現呢?通過對 Android 特性的理解以及思考,發現能夠是用多任務分屏顯示方式實現不一樣 Tab 多進程 Activitys 的顯示和隱藏。讓不一樣Tab打開的 Activitys 分屬於不一樣 Task,每一個 task 擁有一個 Activity 棧來管理其中 Activity,切換 tab 要作的就是不一樣 Task 的切換。這樣邏輯很是清晰,也符合快速 Pad 化的原則。那麼具體該怎麼實現呢?
爲每一個 Tab 打開的第一個 Activity 提供一個不一樣的 TaskAffinity
首先咱們來了解,什麼是 TaskAffinity?
在某些狀況下,Android 須要知道一個 Activity 屬於哪一個 Task,這是經過任務共用性(TaskAffinity)完成的,TaskAffinity 爲運行一個或多個Activity 的 task 提供一個獨特的名稱,當使用 Intent.FLAG_ACTIVITY_NEW_TASK 標誌的 Activity,併爲該 Activity 聲明一個獨特的 TaskAffinity 時,該 Activity 再也不運行在啓動它的 Task 裏,而是會從新啓動一個新的 Task,新的 task 管理一個新的 Activity 棧,而打開的這個 Activity 則位於棧底。
瞭解了 TaskAffinity,咱們在配置文件中爲打開的多進程 Activity 設置相關 tab 的 TaskAffinity 值
下面展現對 web 進程 Activity 的處理
<activity android:name=" BrowserActivity1" android:process=":web" android:taskAffinity="com.tab1. BrowserActivity1" android:theme="@style/Default.Transparent" /> <activity android:name=" BrowserActivity2" android:process=":web" android:taskAffinity="com.tab2.BrowserActivity2" android:theme="@style/Default.Transparent"/> ........
在不一樣 Tab 打開的 BrowserActivity,都爲它們設置了不一樣的 TaskAffinity,在代碼中當發現打開的頁面是 Web 頁面時,則在哪一個Tab打開,頁面重定向到設置了相應 TaskAffinity 的 Activity上。
public void startActivityForResult(Intent intent) { if(isBrowserActivity(intent)){ //純打開QQBrowserActivity int curTab = getTabIndex(); //獲取當前Tab索引 Class<?> c = getBrowserMap().get(curTab); //取出相應打開的Activity redirectAndOpenInNewTask() //重定向 } ...... ...... }
這樣就爲在不一樣 Tab 打開的 Activity 建立了不一樣的 Task。而後在切換Tab時經過發送廣播動態的顯示和隱藏 Task,
public void onTabSelected(int curTabIndex) { Intent i = new Intent("action"); i.putExtra("cur_Tab_Id",curTabIndex); //切換到當前Tab的索引 sendBroadcast(i); }
在 Task 的根 Activity 中接收廣播,處理 Task 顯示和隱藏邏輯
public void onReceive(Context context, Intent intent) { int tab = intent.getIntExtra(CUR_TAB_ID,-1); if(tabIndex>=0 && tabIndex == tab){ moveTaskToFront(mActivity.getTaskId()); //移動當前Task移入後臺 }else{ moveTaskToBack(); //把該Activity所屬Task移動到前臺 } }
到這裏基本上解決了多進程 Activity 與主 Activity 同屏顯示所帶來的問題。
經過上述方案,以及一些問題的巧妙解決,終於實現了 MyApp Pad 化的快速開發,並且 MyApp for Pad 第一個版本的發佈上線,到如今6到7個版本的迭代,一直都是穩定運行的。該方案的優勢是,只要維護好架構,其餘開發者在對單個頁面改造時,不須要管它是真正 Activity 仍是 Fragment,只要知道這些頁面表現的都是 Activity 的行爲,就和在手機 APP 上開發是同樣的。
經過 MyApp Pad 化開發方案的實現,咱們想咱們這個方案是否能夠寫成一個通用的手機 App Pad 化組件,爲公司的其餘Android產品Pad化提供技術支持。就算你的 APP 佈局並非 Tab 方式,咱們開放出一個 Base Activity,其餘 App 的 Activity 經過繼承 Base,就能自動轉換爲Fragment,而且能爲多進程 Activity 提供處理方案。但這確定須要考慮更多的狀況,和解決更多問題。路漫漫其修遠兮,吾將上下而求索。期待完善的 Android App PAD 組件能與你們見面。
若是你以爲內容意猶未盡,若是你想了解更多相關信息,請掃描如下二維碼,關注咱們的公衆帳號,能夠獲取更多技術類乾貨,還有精彩活動與你分享~
騰訊 Bugly是一款專爲移動開發者打造的質量監控工具,幫助開發者快速,便捷的定位線上應用崩潰的狀況以及解決方案。智能合併功能幫助開發同窗把天天上報的數千條 Crash 根據根因合併分類,每日日報會列出影響用戶數最多的崩潰,精準定位功能幫助開發同窗定位到出問題的代碼行,實時上報能夠在發佈後快速的瞭解應用的質量狀況,適配最新的 iOS, Android 官方操做系統,鵝廠的工程師都在使用,快來加入咱們吧!