ActionBar是android的一个非常重要开发组件,在很多商业应用中到处可见,也是很多android开发人员必须熟练掌握的开发技术,下面就从源码角度来分析ActionBar的实现过程。
从哪里开始呢?
我们回忆一下在Activity中获取ActionBar的方法为getActionBar(),那就从getActionBar()开始研究吧!
打开getActionBar()的代码实现如下:
public ActionBar getActionBar() {
initActionBar();
return mActionBar;
}
就简简单单的调用了initActionBar()方法,然后返回mActionBar了。那么mActionBar应该是在initActionBar()中进行实例化的了,我们看一下initActionBar()的代码
private void initActionBar() {
Window window = getWindow();
window.getDecorView();
if (isChild() || !window.hasFeature(Window.FEATURE_ACTION_BAR) || mActionBar != null) {
return;
}
mActionBar = new ActionBarImpl(this);
mActionBar.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp);
}
代码首先是获取窗口类window,然后初始化decorView,接着判断是否嵌套Activity,或者是否使用ActionBar或者mActionBar是否为空,由于是第一次调用,默认情况下这三个条件返回的结果是false;接着就进行mActionBar的实例化操作,可以看到,mActionBar的具体实现交由ActionBarImpl来进行了
抽象类Window的具体实现类是哪个?
这里需要看一下window的具体实现类是哪个呢?我们看到Window这个类是个抽象类,具体实现类是由Activity执行attach()方法的时候才实例化的,我们看一下Activity的attach方法代码
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) {
attachBaseContext(context);
mFragments.attachActivity(this, mContainer, null);
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(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);
}
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
}
可以看到window是在Activity在执行attach方法的时候创建并初始化的,这里就调用了一个PolicyManager.makeNewWindow(this)方法进行创建window,跟踪到类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 {
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);
}
}
private PolicyManager() {}
public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context);
}
public static LayoutInflater makeNewLayoutInflater(Context context) {
return sPolicy.makeNewLayoutInflater(context);
}
public static WindowManagerPolicy makeNewWindowManager() {
return sPolicy.makeNewWindowManager();
}
public static FallbackEventHandler makeNewFallbackEventHandler(Context context) {
return sPolicy.makeNewFallbackEventHandler(context);
}
}
原来策略管理器PolicyManager在static <init>中使用Class.forName()方法动态加载了“com.android.internal.policy.impl.Policy”这个类,并进行实例化,后面的几个静态方法都交由这个类来实现,我们看一下里面的代码:
public class Policy implements IPolicy {
private static final String TAG = "PhonePolicy";
private static final String[] preload_classes = {
"com.android.internal.policy.impl.PhoneLayoutInflater",
"com.android.internal.policy.impl.PhoneWindow",
"com.android.internal.policy.impl.PhoneWindow$1",
"com.android.internal.policy.impl.PhoneWindow$DialogMenuCallback",
"com.android.internal.policy.impl.PhoneWindow$DecorView",
"com.android.internal.policy.impl.PhoneWindow$PanelFeatureState",