}
…
}
这个函数定义在文件frameworks/base/core/java/android/app/Activity.java中。
函数首先调用PolicyManager类的静态成员函数makeNewWindow来创建一个类型为PhoneWindow的应用程序窗口,并且保存 在Activity类的成员变量mWindow中。有了这个类型为PhoneWindow的应用程序窗口,函数接下来还会调用它的成员函数 setCallback、setSoftInputMode和setWindowManager来设置窗口回调接口、软键盘输入区域的显示模式和本地窗口 管理器。
PhoneWindow类的成员函数setCallback、setSoftInputMode和setWindowManager都是从父类 Window继承下来的,因此,接下来我们就继续分析PolicyManager类的静态成员函数makeNewWindow,以及Window类的成员 函数setCallback、setSoftInputMode和setWindowManager的实现。
Step 2. PolicyManager.makeNewWindow
public final class PolicyManager { |
private static final String POLICY_IMPL_CLASS_NAME =
“com.android.internal.policy.impl.Policy”;
private static final IPolicy sPolicy;
static {
// Pull in the actual implementation of the policy at run-time
try {
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
POLICY_IMPL_CLASS_NAME + " could not be loaded", ex);
} catch (InstantiationException ex) {
throw new RuntimeException(
POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(
POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
}
}
…
// The static methods to spawn new policy-specific objects
public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context);
}
…
}
这个函数定义在文件frameworks/base/core/java/com/android/internal/policy/PolicyManager.java中。
PolicyManager是一个窗口管理策略类,它在第一次被使用的时候,就会创建一个Policy类实例,并且保存在静态成员变量sPolicy中, 以后PolicyManager类的窗口管理策略就是通过这个Policy类实例来实现的,例如,PolicyManager类的静态成员函数 makeNewWindow就是通过调用这个Policy类实例的成员函数makeNewWindow来创建一个具体的应用程序窗口的。
接下来,我们就继续分析Policy类的成员函数makeNewWindow的实现。
Step 3. Policy.makeNewWindow
public class Policy implements IPolicy { |
…
public PhoneWindow makeNewWindow(Context context) {
return new PhoneWindow(context);
}
…
}
这个函数定义在文件frameworks/base/policy/src/com/android/internal/policy/impl/Policy.java中。
Policy类的成员函数makeNewWindow的实现很简单,它只是创建了一个PhoneWindow对象,然后返回给调用者。
接下来,我们就继续分析PhoneWindow类的构造函数的实现,以便可以了解一个类型为PhoneWindow的应用程序窗口的创建过程
Step 4. new PhoneWindow
public class PhoneWindow extends Window implements MenuBuilder.Callback { |
…
// This is the top-level view of the window, containing the window decor.
private DecorView mDecor;
// This is the view in which the window contents are placed. It is either
// mDecor itself, or a child of mDecor where the contents go.
private ViewGroup mContentParent;
…
private LayoutInflater mLayoutInflater;
…
public PhoneWindow(Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
}
…
}
这个函数定义在文件frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中。
PhoneWindow类的构造函数很简单,它首先调用父类Window的构造函数来执行一些初始化操作,接着再调用LayoutInflater的静态成员函数from创建一个LayoutInflater实例,并且保存在成员变量mLayoutInflater中。这样,PhoneWindow类以后就可以通过成员变量mLayoutInflater来创建应用程序窗口的视图,这个视图使用类型为DecorView的成员变量mDecor来描述。PhoneWindow类还有另外一个类型为ViewGroup的成员变量mContentParent,用来描述一个视图容器,这个容器存放的就是成员变量mDecor所描述的视图的内容,不过这个容器也有可能指向的是mDecor本身。在后面的文章中,我们再详细分析类型为PhoneWindow的应用程序窗口的视图的创建过程。
Window的构造函数定义在文件frameworks/base/core/java/android/view/Window.java中,它的实现很简单,只是初始化了其成员变量mContext,如下所示:
public abstract class Window { |
…
private final Context mContext;
…
public Window(Context context) {
mContext = context;
}
…
}
从前面的调用过程可以知道,参数context描述的是正在启动的Activity组件,将它保存在Window类的成员变量mContext之后,Window类就可以通过它来访问与Activity组件相关的资源了。
这一步执行完成之后,回到前面的Step 1中,即Activity类的成员函数attach中,接下来就会继续调用前面所创建的PhoneWindow对象从父类Window继承下来的成员函数setCallback来设置窗口回调接口,因此,接下来我们就继续分析Window类的成员函数setCallback的实现。
Step 5. Window.setCallback
public abstract class Window { |
…
private Callback mCallback;
…
/**
-
Set the Callback interface for this window, used to intercept key
-
events and other dynamic operations in the window.
-
@param callback The desired Callback interface.
*/
public void setCallback(Callback callback) {
mCallback = callback;
}
…
}
这个函数定义在文件frameworks/base/core/java/android/view/Window.java中。
正在启动的Activity组件会将它所实现的一个Callback接口设置到与它所关联的一个PhoneWindow对象的父类Window的成员变 量mCallback中去,这样当这个PhoneWindow对象接收到系统给它分发的IO输入事件,例如,键盘和触摸屏事件,转发给与它所关联的 Activity组件处理。
这一步执行完成之后,回到前面的Step 1中,即Activity类的成员函数attach中,接下来就会继续调用前面所创建的PhoneWindow对象从父类Window继承下来的成员函数 setSoftInputMode来设置应用程序窗口的软键盘输入区域的显示模式,因此,接下来我们就继续分析Window类的成员函数 setSoftInputMode的实现。
Step 6. Window.setSoftInputMode
public abstract class Window { |
…
private boolean mHasSoftInputMode = false;
…
public void setSoftInputMode(int mode) {
final WindowManager.LayoutParams attrs = getAttributes();
if (mode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
attrs.softInputMode = mode;
mHasSoftInputMode = true;
} else {
mHasSoftInputMode = false;
}
if (mCallback != null) {
mCallback.onWindowAttributesChanged(attrs);
}
}
…
}
这个函数定义在文件frameworks/base/core/java/android/view/Window.java中。
参数mode有SOFT_INPUT_STATE_UNSPECIFIED、SOFT_INPUT_STATE_UNCHANGED、SOFT_INPUT_STATE_HIDDEN、SOFT_INPUT_STATE_ALWAYS_HIDDEN、SOFT_INPUT_STATE_VISIBLE和SOFT_INPUT_STATE_ALWAYS_VISIBLE一共六个取值,用来描述窗口的软键盘输入区域的显示模式,它们的含义如下所示:
-
SOFT_INPUT_STATE_UNSPECIFIED:没有指定软键盘输入区域的显示状态。
-
SOFT_INPUT_STATE_UNCHANGED:不要改变软键盘输入区域的显示状态。
-
SOFT_INPUT_STATE_HIDDEN:在合适的时候隐藏软键盘输入区域,例如,当用户导航到当前窗口时。
-
SOFT_INPUT_STATE_ALWAYS_HIDDEN:当窗口获得焦点时,总是隐藏软键盘输入区域。
-
SOFT_INPUT_STATE_VISIBLE:在合适的时候显示软键盘输入区域,例如,当用户导航到当前窗口时。
-
SOFT_INPUT_STATE_ALWAYS_VISIBLE:当窗口获得焦点时,总是显示软键盘输入区域。
当参数mode的值不等于SOFT_INPUT_STATE_UNSPECIFIED时,就表示当前窗口被指定软键盘输入区域的显示模式,这时候Window类的成员函数setSoftInputMode就会将成员变量mHasSoftInputMode的值设置为true,并且将这个显示模式保存在用来描述窗口布局属性的一个WindowManager.LayoutParams对象的成员变量softInputMode中,否则的话,就会将成员变量mHasSoftInputMode的值设置为false。
设置完成窗口的软键盘输入区域的显示模式之后,如果Window类的成员变量mCallback指向了一个窗口回调接口,那么Window类的成员函数setSoftInputMode还会调用它的成员函数onWindowAttributesChanged来通知与窗口所关联的Activity组件,它的窗口布局属性发生了变化。
这一步执行完成之后,回到前面的Step 1中,即Activity类的成员函数attach中,接下来就会继续调用前面所创建的PhoneWindow对象从父类Window继承下来的成员函数setWindowManager来设置应用程序窗口的本地窗口管理器,因此,接下来我们就继续分析Window类的成员函数setWindowManager的实现。
Step 7. Window.setWindowManager
public abstract class Window { |
…
private WindowManager mWindowManager;
private IBinder mAppToken;
private String mAppName;
…
public void setWindowManager(WindowManager wm,
IBinder appToken, String appName) {
mAppToken = appToken;
mAppName = appName;
if (wm == null) {
wm = WindowManagerImpl.getDefault();
}
mWindowManager = new LocalWindowManager(wm);
}
最后
简历首选内推方式,速度快,效率高啊!然后可以在拉钩,boss,脉脉,大街上看看。简历上写道熟悉什么技术就一定要去熟悉它,不然被问到不会很尴尬!做过什么项目,即使项目体量不大,但也一定要熟悉实现原理!不是你负责的部分,也可以看看同事是怎么实现的,换你来做你会怎么做?做过什么,会什么是广度问题,取决于项目内容。但做过什么,达到怎样一个境界,这是深度问题,和个人学习能力和解决问题的态度有关了。大公司看深度,小公司看广度。大公司面试你会的,小公司面试他们用到的你会不会,也就是岗位匹配度。
选定你想去的几家公司后,先去一些小的公司练练,学习下面试技巧,总结下,也算是熟悉下面试氛围,平时和同事或者产品PK时可以讲得头头是道,思路清晰至极,到了现场真的不一样,怎么描述你所做的一切,这绝对是个学术性问题!
面试过程一定要有礼貌!即使你觉得面试官不尊重你,经常打断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。
金九银十面试季,跳槽季,整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
怎么描述你所做的一切,这绝对是个学术性问题!
面试过程一定要有礼貌!即使你觉得面试官不尊重你,经常打断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。
金九银十面试季,跳槽季,整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中…(img-D9jSJPiw-1643525027354)]