摘要:在代碼中的直接應用是或者是。就像一個控制器,統籌視圖的添加與顯示,以及通過其他回調方法,來與以及進行交互。創建需要通過創建,通過將加載其中,并將交給,進行視圖繪制以及其他交互。創建機制分析實例的創建中執行,從而生成了的實例。
目錄介紹
01.Window,View,子Window
02.什么是Activity
03.什么是Window
04.什么是DecorView
05.什么是View
06.關系結構圖
07.Window創建過程
08.創建機制分析
8.1 Activity實例的創建
8.2 Activity中Window的創建
8.3 DecorView的創建
彈窗系列博客
01.Activity、Window、View三者關系
深入分析Activity、Window、View三者之間的關系
02.Toast源碼深度分析
最簡單的創建,簡單改造避免重復創建,show()方法源碼分析,scheduleTimeoutLocked吐司如何自動銷毀的,TN類中的消息機制是如何執行的,普通應用的Toast顯示數量是有限制的,用代碼解釋為何Activity銷毀后Toast仍會顯示,Toast偶爾報錯Unable to add window是如何產生的,Toast運行在子線程問題,Toast如何添加系統窗口的權限等等
03.DialogFragment源碼分析
最簡單的使用方法,onCreate(@Nullable Bundle savedInstanceState)源碼分析,重點分析彈窗展示和銷毀源碼,使用中show()方法遇到的IllegalStateException分析
04.Dialog源碼分析
AlertDialog源碼分析,通過AlertDialog.Builder對象設置屬性,Dialog生命周期,Dialog中show方法展示彈窗分析,Dialog的dismiss銷毀彈窗,Dialog彈窗問題分析等等
05.PopupWindow源碼分析
顯示PopupWindow,注意問題寬和高屬性,showAsDropDown()源碼,dismiss()源碼分析,PopupWindow和Dialog有什么區別?為何彈窗點擊一下就dismiss呢?
06.Snackbar源碼分析
最簡單的創建,Snackbar的make方法源碼分析,Snackbar的show顯示與點擊消失源碼分析,顯示和隱藏中動畫源碼分析,Snackbar的設計思路,為什么Snackbar總是顯示在最下面
07.彈窗常見問題
DialogFragment使用中show()方法遇到的IllegalStateException,什么常見產生的?Toast偶爾報錯Unable to add window,Toast運行在子線程導致崩潰如何解決?
09.onAttachedToWindow和onDetachedFromWindow
onAttachedToWindow的調用過程,onDetachedFromWindow可以做什么?
10.DecorView介紹
什么是DecorView,DecorView的創建,DecorView的顯示,深度解析
01.Window,View,子Window
彈窗有哪些類型
使用子窗口:在 Android 進程內,我們可以直接使用類型為子窗口類型的窗口。在 Android 代碼中的直接應用是 PopupWindow 或者是 Dialog 。這當然可以,不過這種窗口依賴于它的宿主窗口,它可用的條件是你的宿主窗口可用
采用View系統:使用 View 系統去模擬一個窗口行為,且能更加快速的實現動畫效果,比如SnackBar 就是采用這套方案
使用系統窗口:比如吐司Toast
02.什么是ActivityActivity并不負責視圖控制,它只是控制生命周期和處理事件。真正控制視圖的是Window。一個Activity包含了一個Window,Window才是真正代表一個窗口。
Activity就像一個控制器,統籌視圖的添加與顯示,以及通過其他回調方法,來與Window、以及View進行交互。
03.什么是Window
Window是什么?
表示一個窗口的概念,是所有View的直接管理者,任何視圖都通過Window呈現(點擊事件由Window->DecorView->View; Activity的setContentView底層通過Window完成)
Window是一個抽象類,具體實現是PhoneWindow。PhoneWindow中有個內部類DecorView,通過創建DecorView來加載Activity中設置的布局R.layout.activity_main。
創建Window需要通過WindowManager創建,通過WindowManager將DecorView加載其中,并將DecorView交給ViewRoot,進行視圖繪制以及其他交互。
WindowManager是外界訪問Window的入口
Window具體實現位于WindowManagerService中
WindowManager和WindowManagerService的交互是通過IPC完成
如何通過WindowManager添加Window(代碼實現)?
如下所示
//1. 控件 Button button = new Button(this); button.setText("Window Button"); //2. 布局參數 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不然會異常: 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的子類,它可以被認為是Android視圖樹的根節點視圖。
DecorView作為頂級View,一般情況下它內部包含一個豎直方向的LinearLayout,在這個LinearLayout里面有上下三個部分,上面是個ViewStub,延遲加載的視圖(應該是設置ActionBar,根據Theme設置),中間的是標題欄(根據Theme設置,有的布局沒有),下面的是內容欄。
具體情況和Android版本及主體有關,以其中一個布局為例,如下所示:
在Activity中通過setContentView所設置的布局文件其實就是被加到內容欄之中的,成為其唯一子View,就是上面的id為content的FrameLayout中,在代碼中可以通過content來得到對應加載的布局。
ViewGroup content = (ViewGroup)findViewById(android.R.id.content); ViewGroup rootView = (ViewGroup) content.getChildAt(0);06.關系結構圖
Activity 與 PhoneWindow 與 DecorView 關系圖
07.Window創建過程
App點擊桌面圖片啟動過程
window啟動流程
Activity 與 PhoneWindow 與 DecorView 之間什么關系?
一個 Activity 對應一個 Window 也就是 PhoneWindow,一個 PhoneWindow 持有一個 DecorView 的實例,DecorView 本身是一個 FrameLayout。
08.創建機制分析 8.1 Activity實例的創建
ActivityThread中執行performLaunchActivity,從而生成了Activity的實例。源碼如下所示,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的創建
從上面的performLaunchActivity可以看出,在創建Activity實例的同時,會調用Activity的內部方法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的創建
用戶執行Activity的setContentView方法,內部是調用PhoneWindow的setContentView方法,在PhoneWindow中完成DecorView的創建。流程
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); } } ... }關于其他內容介紹 01.關于博客匯總鏈接
1.技術博客匯總
2.開源項目匯總
3.生活博客匯總
4.喜馬拉雅音頻匯總
5.其他匯總
02.關于我的博客github:https://github.com/yangchong211
知乎:https://www.zhihu.com/people/...
簡書:http://www.jianshu.com/u/b7b2...
csdn:http://my.csdn.net/m0_37700275
喜馬拉雅聽書:http://www.ximalaya.com/zhubo...
開源中國:https://my.oschina.net/zbj161...
泡在網上的日子: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文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74696.html
摘要:指向的主要是實現和通信的。子不能單獨存在,需附屬特定的父。系統需申明權限才能創建。和類似,同樣是通過來實現。將添加到中顯示。方法完成的顯示。執行的檢查參數等設置檢查將保存到中將保存到中。因為通過和的將無法獲取到從而導致失敗。 目錄介紹 10.0.0.1 Window是什么?如何通過WindowManager添加Window(代碼實現)?WindowManager的主要功能是什么? 1...
摘要:前段時間,前同事跳槽,機緣巧合下面了阿里,本來憑著試一試的態度,卻不料好事成雙,拿到了,而且薪資也了。面就沒啥東西可聊的,基本上就是對此次面試的一個評價定薪等等一些之內的話題。如果是現場面試,記得關注當天的天氣,提前查一下路線。 ...
摘要:獲取短信內容的方法短信內容數據也是系統提供的,獲取方法如下獲取方法如下微信公眾號程序員插入數據測試數據中。。。。。 showImg(https://segmentfault.com/img/remote/1460000019975019?w=157&h=54); 極力推薦文章:歡迎收藏Android 干貨分享 showImg(https://segmentfault.com/img/...
閱讀 2344·2021-11-23 09:51
閱讀 1999·2021-10-14 09:43
閱讀 2760·2021-09-27 13:35
閱讀 1144·2021-09-22 15:54
閱讀 2495·2021-09-13 10:36
閱讀 3784·2019-08-30 15:56
閱讀 3404·2019-08-30 14:09
閱讀 1711·2019-08-30 12:57