android phone activity,[Android-FrameWork]Android-PhoneWindow详细分析

我们都知道Activity的层有一个Window也有一个WindowManage其中对应如下

Activity所拥有的Window与 WindowManage

1.PhoneWindow

2.PhoneWindowManage

在刚开始我们设置的时候是这样设置的

setContentView(R.layout.activity_main);

我们跟进一下

public void setContentView(@LayoutRes int layoutResID) {

getWindow().setContentView(layoutResID); //主要看这个,我们先看看这个getWindow是什么

initWindowDecorActionBar();//这个是DecorView初始化ActionBar的,

//DecorView为整个Activity也就是整个

//PhoneWindow底层的View

}

我们先看看这个getWindow是什么

public Window getWindow() {

return mWindow; //直接return了一个mWindow

}

//看一下这个mWindow是什么

mWindow = new PhoneWindow(this, window, activityConfigCallback); //底层就是PhoneWindow

//再来看一下WindowManage

mWindowManager = mWindow.getWindowManager();

//也就是说用的是PhoneWindow的WindowManager

我们继续跟进到PhoneWindow类里边

回到我们的setContentView

/**

* XINHAO_HAN 设置Activity的View

* @param layoutResID

*/

@Override

public void setContentView(int layoutResID) {

// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window

// decor, when theme attributes and the like are crystalized. Do not check the feature

// before this happens.

/**

* 如果第一次设置 mContentParent为ViewGroup

*/

if (mContentParent == null) {

/**

* 就开始初始化

*/

installDecor();

} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {

/**

* 否则就移除掉所有子View等待重新添加

*/

mContentParent.removeAllViews();

}

if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {

final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,

getContext());

transitionTo(newScene);

} else {

mLayoutInflater.inflate(layoutResID, mContentParent);

}

mContentParent.requestApplyInsets();

final Callback cb = getCallback();

if (cb != null && !isDestroyed()) {

//如果视图跟新就通知外部类

cb.onContentChanged();

}

mContentParentExplicitlySet = true;

}

我们继续看一下 installDecor();

private void installDecor() {

mForceDecorInstall = false;

//如果DecorView为空就开始设置DecorView

if (mDecor == null) {

//Decor就是在这里创建的,我们看一下这个方法

mDecor = generateDecor(-1);

//获取焦点

mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);

mDecor.setIsRootNamespace(true);

if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {

mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);

}

} else {

mDecor.setWindow(this);

}

......

}

我们看一下这个方法 generateDecor(-1);

protected DecorView generateDecor(int featureId) {

// System process doesn't have application context and in that case we need to directly use

// the context we have. Otherwise we want the application context, so we don't cling to the

// activity.

Context context;

if (mUseDecorContext) {

Context applicationContext = getContext().getApplicationContext();

if (applicationContext == null) {

context = getContext();

} else {

context = new DecorContext(applicationContext, getContext().getResources());

if (mTheme != -1) {

context.setTheme(mTheme);

}

}

} else {

context = getContext();

}

return new DecorView(context, featureId, this, getAttributes());

}

这块是直接new了一个DecorView,就相当于要添加到PhoneWindow里边的View

mEnterTransition = getTransition(mEnterTransition, null,

R.styleable.Window_windowEnterTransition);

mReturnTransition = getTransition(mReturnTransition, USE_DEFAULT_TRANSITION,

R.styleable.Window_windowReturnTransition);

mExitTransition = getTransition(mExitTransition, null,

R.styleable.Window_windowExitTransition);

mReenterTransition = getTransition(mReenterTransition, USE_DEFAULT_TRANSITION,

R.styleable.Window_windowReenterTransition);

mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition, null,

R.styleable.Window_windowSharedElementEnterTransition);

mSharedElementReturnTransition = getTransition(mSharedElementReturnTransition,

USE_DEFAULT_TRANSITION,

R.styleable.Window_windowSharedElementReturnTransition);

mSharedElementExitTransition = getTransition(mSharedElementExitTransition, null,

R.styleable.Window_windowSharedElementExitTransition);

mSharedElementReenterTransition = getTransition(mSharedElementReenterTransition,

USE_DEFAULT_TRANSITION,

R.styleable.Window_windowSharedElementReenterTransition);

if (mAllowEnterTransitionOverlap == null) {

mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(

R.styleable.Window_windowAllowEnterTransitionOverlap, true);

}

if (mAllowReturnTransitionOverlap == null) {

mAllowReturnTransitionOverlap = getWindowStyle().getBoolean(

R.styleable.Window_windowAllowReturnTransitionOverlap, true);

}

if (mBackgroundFadeDurationMillis < 0) {

mBackgroundFadeDurationMillis = getWindowStyle().getInteger(

R.styleable.Window_windowTransitionBackgroundFadeDuration,

DEFAULT_BACKGROUND_FADE_DURATION_MS);

}

if (mSharedElementsUseOverlay == null) {

mSharedElementsUseOverlay = getWindowStyle().getBoolean(

R.styleable.Window_windowSharedElementsUseOverlay, true);

}

//这块是设置了一些用户设置的主题什么的

然后感觉没了? 没了??不可能啊,它应该是有一个东西添加到WindowManager里边的,否则什么都不会显示

然后我在ActivityThread里边找到了它添加的一些方法

if (r.window == null && !a.mFinished && willBeVisible) {

r.window = r.activity.getWindow();

View decor = r.window.getDecorView();

decor.setVisibility(View.INVISIBLE);

ViewManager wm = a.getWindowManager();

WindowManager.LayoutParams l = r.window.getAttributes();

a.mDecor = decor;

l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;

l.softInputMode |= forwardBit;

if (r.mPreserveWindow) {

a.mWindowAdded = true;

r.mPreserveWindow = false;

// Normally the ViewRoot sets up callbacks with the Activity

// in addView->ViewRootImpl#setView. If we are instead reusing

// the decor view we have to notify the view root that the

// callbacks may have changed.

ViewRootImpl impl = decor.getViewRootImpl();

if (impl != null) {

impl.notifyChildRebuilt();

}

}

if (a.mVisibleFromClient) {

if (!a.mWindowAdded) {

a.mWindowAdded = true;

//重点在这里------------------------------------------------------------------------------------

wm.addView(decor, l);

} else {

// The activity will get a callback for this {@link LayoutParams} change

// earlier. However, at that time the decor will not be set (this is set

// in this method), so no action will be taken. This call ensures the

// callback occurs with the decor set.

a.onWindowAttributesChanged(l);

}

}

我们可以看出在Activity相当于一个PhoneWindow一个维护类.

当所有东西都初始化好了(getDecorView和PhoneWindow)以后再ActivityThread中直接调用

知识点(总结)

1.Activity中的setContentView实际上是给Activity对应的Window设置

2.Activity对应的Window是PhoneWindow

3.Activity的根目录为DecorView,在 Android当中有一个实体id android.R.id.content

4.Activity添加布局是在ActivityThread中添加的,并且在PhoneWindow初始化好之后(DecorView)

5.DecorView的布局是集成于FramLayout,并且有统一的格式,包括我们看到的,状态栏,布局,TitleBar,

6.可以说是以外得把,你可以试试用Activity的WindowManager添加一个View,然后用getApplicationContext的WindowManager添加一个View然后对比效果

效果是如下的,Activity-WindowManager添加的View只能依附在于Activity上不能依附在所有APP上边,Activity销毁后可能会提示窗口泄露,没有移除掉,但是不会奔溃,只是提示,Activity-WindowManager所添加的View是根据Activity的生命周期而变化的(绑定在一起的),而getApplicationContext所添加的WindowManager的View是飘在整个系统上边的

另外还有一点,就是Dialog其实并不需要在Activity上弹出,这个大家可以参考一下,而且这个是有依据的,大家手机电量低于15%的时候,是不是不管你在那块都会给你弹出一个Dialog提示电量低于15%,请连接电源.这个是一个知识点奥.

有错误的地方欢迎大神指出来,大家共同进步 _

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值