摘要:在代碼中的直接應(yīng)用是或者是。就像一個(gè)控制器,統(tǒng)籌視圖的添加與顯示,以及通過(guò)其他回調(diào)方法,來(lái)與以及進(jìn)行交互。創(chuàng)建需要通過(guò)創(chuàng)建,通過(guò)將加載其中,并將交給,進(jìn)行視圖繪制以及其他交互。創(chuàng)建機(jī)制分析實(shí)例的創(chuàng)建中執(zhí)行,從而生成了的實(shí)例。
目錄介紹
01.Window,View,子Window
02.什么是Activity
03.什么是Window
04.什么是DecorView
05.什么是View
06.關(guān)系結(jié)構(gòu)圖
07.Window創(chuàng)建過(guò)程
08.創(chuàng)建機(jī)制分析
8.1 Activity實(shí)例的創(chuàng)建
8.2 Activity中Window的創(chuàng)建
8.3 DecorView的創(chuàng)建
彈窗系列博客
01.Activity、Window、View三者關(guān)系
深入分析Activity、Window、View三者之間的關(guān)系
02.Toast源碼深度分析
最簡(jiǎn)單的創(chuàng)建,簡(jiǎn)單改造避免重復(fù)創(chuàng)建,show()方法源碼分析,scheduleTimeoutLocked吐司如何自動(dòng)銷毀的,TN類中的消息機(jī)制是如何執(zhí)行的,普通應(yīng)用的Toast顯示數(shù)量是有限制的,用代碼解釋為何Activity銷毀后Toast仍會(huì)顯示,Toast偶爾報(bào)錯(cuò)Unable to add window是如何產(chǎn)生的,Toast運(yùn)行在子線程問(wèn)題,Toast如何添加系統(tǒng)窗口的權(quán)限等等
03.DialogFragment源碼分析
最簡(jiǎn)單的使用方法,onCreate(@Nullable Bundle savedInstanceState)源碼分析,重點(diǎn)分析彈窗展示和銷毀源碼,使用中show()方法遇到的IllegalStateException分析
04.Dialog源碼分析
AlertDialog源碼分析,通過(guò)AlertDialog.Builder對(duì)象設(shè)置屬性,Dialog生命周期,Dialog中show方法展示彈窗分析,Dialog的dismiss銷毀彈窗,Dialog彈窗問(wèn)題分析等等
05.PopupWindow源碼分析
顯示PopupWindow,注意問(wèn)題寬和高屬性,showAsDropDown()源碼,dismiss()源碼分析,PopupWindow和Dialog有什么區(qū)別?為何彈窗點(diǎn)擊一下就dismiss呢?
06.Snackbar源碼分析
最簡(jiǎn)單的創(chuàng)建,Snackbar的make方法源碼分析,Snackbar的show顯示與點(diǎn)擊消失源碼分析,顯示和隱藏中動(dòng)畫(huà)源碼分析,Snackbar的設(shè)計(jì)思路,為什么Snackbar總是顯示在最下面
07.彈窗常見(jiàn)問(wèn)題
DialogFragment使用中show()方法遇到的IllegalStateException,什么常見(jiàn)產(chǎn)生的?Toast偶爾報(bào)錯(cuò)Unable to add window,Toast運(yùn)行在子線程導(dǎo)致崩潰如何解決?
09.onAttachedToWindow和onDetachedFromWindow
onAttachedToWindow的調(diào)用過(guò)程,onDetachedFromWindow可以做什么?
10.DecorView介紹
什么是DecorView,DecorView的創(chuàng)建,DecorView的顯示,深度解析
01.Window,View,子Window
彈窗有哪些類型
使用子窗口:在 Android 進(jìn)程內(nèi),我們可以直接使用類型為子窗口類型的窗口。在 Android 代碼中的直接應(yīng)用是 PopupWindow 或者是 Dialog 。這當(dāng)然可以,不過(guò)這種窗口依賴于它的宿主窗口,它可用的條件是你的宿主窗口可用
采用View系統(tǒng):使用 View 系統(tǒng)去模擬一個(gè)窗口行為,且能更加快速的實(shí)現(xiàn)動(dòng)畫(huà)效果,比如SnackBar 就是采用這套方案
使用系統(tǒng)窗口:比如吐司Toast
02.什么是ActivityActivity并不負(fù)責(zé)視圖控制,它只是控制生命周期和處理事件。真正控制視圖的是Window。一個(gè)Activity包含了一個(gè)Window,Window才是真正代表一個(gè)窗口。
Activity就像一個(gè)控制器,統(tǒng)籌視圖的添加與顯示,以及通過(guò)其他回調(diào)方法,來(lái)與Window、以及View進(jìn)行交互。
03.什么是Window
Window是什么?
表示一個(gè)窗口的概念,是所有View的直接管理者,任何視圖都通過(guò)Window呈現(xiàn)(點(diǎn)擊事件由Window->DecorView->View; Activity的setContentView底層通過(guò)Window完成)
Window是一個(gè)抽象類,具體實(shí)現(xiàn)是PhoneWindow。PhoneWindow中有個(gè)內(nèi)部類DecorView,通過(guò)創(chuàng)建DecorView來(lái)加載Activity中設(shè)置的布局R.layout.activity_main。
創(chuàng)建Window需要通過(guò)WindowManager創(chuàng)建,通過(guò)WindowManager將DecorView加載其中,并將DecorView交給ViewRoot,進(jìn)行視圖繪制以及其他交互。
WindowManager是外界訪問(wèn)Window的入口
Window具體實(shí)現(xiàn)位于WindowManagerService中
WindowManager和WindowManagerService的交互是通過(guò)IPC完成
如何通過(guò)WindowManager添加Window(代碼實(shí)現(xiàn))?
如下所示
//1. 控件 Button button = new Button(this); button.setText("Window Button"); //2. 布局參數(shù) WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, 0, 0, PixelFormat.TRANSPARENT); layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; layoutParams.gravity = Gravity.LEFT | Gravity.TOP; layoutParams.x = 100; layoutParams.y = 300; // 必須要有type不然會(huì)異常: the specified window type 0 is not valid layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; //3. 獲取WindowManager并添加控件到Window中 WindowManager windowManager = getWindowManager(); windowManager.addView(button, layoutParams);
WindowManager的主要功能是什么?
添加、更新、刪除View
public interface ViewManager{ public void addView(View view, ViewGroup.LayoutParams params); //添加View public void updateViewLayout(View view, ViewGroup.LayoutParams params); //更新View public void removeView(View view); //刪除View }04.什么是DecorView
DecorView是FrameLayout的子類,它可以被認(rèn)為是Android視圖樹(shù)的根節(jié)點(diǎn)視圖。
DecorView作為頂級(jí)View,一般情況下它內(nèi)部包含一個(gè)豎直方向的LinearLayout,在這個(gè)LinearLayout里面有上下三個(gè)部分,上面是個(gè)ViewStub,延遲加載的視圖(應(yīng)該是設(shè)置ActionBar,根據(jù)Theme設(shè)置),中間的是標(biāo)題欄(根據(jù)Theme設(shè)置,有的布局沒(méi)有),下面的是內(nèi)容欄。
具體情況和Android版本及主體有關(guān),以其中一個(gè)布局為例,如下所示:
在Activity中通過(guò)setContentView所設(shè)置的布局文件其實(shí)就是被加到內(nèi)容欄之中的,成為其唯一子View,就是上面的id為content的FrameLayout中,在代碼中可以通過(guò)content來(lái)得到對(duì)應(yīng)加載的布局。
ViewGroup content = (ViewGroup)findViewById(android.R.id.content); ViewGroup rootView = (ViewGroup) content.getChildAt(0);06.關(guān)系結(jié)構(gòu)圖
Activity 與 PhoneWindow 與 DecorView 關(guān)系圖
07.Window創(chuàng)建過(guò)程
App點(diǎn)擊桌面圖片啟動(dòng)過(guò)程
window啟動(dòng)流程
Activity 與 PhoneWindow 與 DecorView 之間什么關(guān)系?
一個(gè) Activity 對(duì)應(yīng)一個(gè) Window 也就是 PhoneWindow,一個(gè) PhoneWindow 持有一個(gè) DecorView 的實(shí)例,DecorView 本身是一個(gè) FrameLayout。
08.創(chuàng)建機(jī)制分析 8.1 Activity實(shí)例的創(chuàng)建
ActivityThread中執(zhí)行performLaunchActivity,從而生成了Activity的實(shí)例。源碼如下所示,ActivityThread類中源碼
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); ... } catch (Exception e) { ... } try { ... if (activity != null) { ... activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor); ... } ... } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { ... } return activity; }8.2 Activity中Window的創(chuàng)建
從上面的performLaunchActivity可以看出,在創(chuàng)建Activity實(shí)例的同時(shí),會(huì)調(diào)用Activity的內(nèi)部方法attach
在attach該方法中完成window的初始化。源碼如下所示,Activity類中源碼
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window, ActivityConfigCallback activityConfigCallback) { mWindow = new PhoneWindow(this, window, activityConfigCallback); mWindow.setWindowControllerCallback(this); mWindow.setCallback(this); mWindow.setOnWindowDismissedCallback(this); mWindow.getLayoutInflater().setPrivateFactory(this); if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) { mWindow.setSoftInputMode(info.softInputMode); } if (info.uiOptions != 0) { mWindow.setUiOptions(info.uiOptions); } }8.3 DecorView的創(chuàng)建
用戶執(zhí)行Activity的setContentView方法,內(nèi)部是調(diào)用PhoneWindow的setContentView方法,在PhoneWindow中完成DecorView的創(chuàng)建。流程
1.Activity中的setContentView
2.PhoneWindow中的setContentView
3.PhoneWindow中的installDecor
public void setContentView(@LayoutRes int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); } @Override public void setContentView(int layoutResID) { ... if (mContentParent == null) { installDecor(); } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); } ... } private void installDecor() { if (mDecor == null) { mDecor = generateDecor(); mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); mDecor.setIsRootNamespace(true); if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) { mDecor.postOnAnimation(mInvalidatePanelMenuRunnable); } } ... }關(guān)于其他內(nèi)容介紹 01.關(guān)于博客匯總鏈接
1.技術(shù)博客匯總
2.開(kāi)源項(xiàng)目匯總
3.生活博客匯總
4.喜馬拉雅音頻匯總
5.其他匯總
02.關(guān)于我的博客github:https://github.com/yangchong211
知乎:https://www.zhihu.com/people/...
簡(jiǎn)書(shū):http://www.jianshu.com/u/b7b2...
csdn:http://my.csdn.net/m0_37700275
喜馬拉雅聽(tīng)書(shū):http://www.ximalaya.com/zhubo...
開(kāi)源中國(guó):https://my.oschina.net/zbj161...
泡在網(wǎng)上的日子:http://www.jcodecraeer.com/me...
郵箱:yangchong211@163.com
阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV
segmentfault頭條:https://segmentfault.com/u/xi...
掘金:https://juejin.im/user/593943...
GitHub鏈接:https://github.com/yangchong211文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/74696.html
摘要:指向的主要是實(shí)現(xiàn)和通信的。子不能單獨(dú)存在,需附屬特定的父。系統(tǒng)需申明權(quán)限才能創(chuàng)建。和類似,同樣是通過(guò)來(lái)實(shí)現(xiàn)。將添加到中顯示。方法完成的顯示。執(zhí)行的檢查參數(shù)等設(shè)置檢查將保存到中將保存到中。因?yàn)橥ㄟ^(guò)和的將無(wú)法獲取到從而導(dǎo)致失敗。 目錄介紹 10.0.0.1 Window是什么?如何通過(guò)WindowManager添加Window(代碼實(shí)現(xiàn))?WindowManager的主要功能是什么? 1...
摘要:前段時(shí)間,前同事跳槽,機(jī)緣巧合下面了阿里,本來(lái)憑著試一試的態(tài)度,卻不料好事成雙,拿到了,而且薪資也了。面就沒(méi)啥東西可聊的,基本上就是對(duì)此次面試的一個(gè)評(píng)價(jià)定薪等等一些之內(nèi)的話題。如果是現(xiàn)場(chǎng)面試,記得關(guān)注當(dāng)天的天氣,提前查一下路線。 ...
摘要:獲取短信內(nèi)容的方法短信內(nèi)容數(shù)據(jù)也是系統(tǒng)提供的,獲取方法如下獲取方法如下微信公眾號(hào)程序員插入數(shù)據(jù)測(cè)試數(shù)據(jù)中。。。。。 showImg(https://segmentfault.com/img/remote/1460000019975019?w=157&h=54); 極力推薦文章:歡迎收藏Android 干貨分享 showImg(https://segmentfault.com/img/...
閱讀 2355·2021-11-23 09:51
閱讀 2006·2021-10-14 09:43
閱讀 2776·2021-09-27 13:35
閱讀 1157·2021-09-22 15:54
閱讀 2510·2021-09-13 10:36
閱讀 3810·2019-08-30 15:56
閱讀 3412·2019-08-30 14:09
閱讀 1722·2019-08-30 12:57