Android的Base初始化,使用代理模式

本文介绍了一种利用代理模式简化Base类的方法,通过定义接口并使用代理类来减少重复代码,实现了更简洁高效的组件初始化过程。

概述

首先,我们的项目一般会有很多的Base类,各种类型,风格的Activity,Fragment,或者是Dialog,然后我们的子类去继承它执行一些统一性的初始化工作,比如初始化一些基础控件,一些topbar之类的。然后,对于方法,我们也是回做一个功能单一的抽取,比如initData,initEvent之类的。但是,每一个Base都是用这样的方式会需要重复不少的代码,因此我们考虑使用一个借口抽象这些方法,然后让Base去实现。但是Base的实现,发现我们可以使用更加简洁的方式去避免在各种初始化的方法中做各种判断,想到这个,我们就可以使用代理模式去实现。

实现

接口方法
public interface ComponentsImpl {
    /**
     * 获取布局id
     *
     * @return layout id
     */
    int getLayoutId();

    /**
     * 恢复数据
     *
     * @param savedInstanceState
     */
    void recoverAndBeforeInfalter(@Nullable Bundle savedInstanceState);

    /**
     * initview,data等东西之前处理,比如全屏之类
     */
    void beforeInit();

    /**
     * 初始化事件监听
     */
    void initEvent();

    /**
     * 初始化基本数据
     */
    void initData();

}
代理类

他的作用主要是被代理类和base类实现。
现在有一个比较好用简单的注入框架叫做ButterKnife,我的一般项目都是使用它做View的init,所以我们这里的代理类还负责为每一个Base进行ButterKnife的引入。

/**
 * Created by liweijie on 2016/5/19.
 * 代理模式,代理组件初始化
 */
public class ComponentsImplProxy implements ComponentsImpl {

    private ComponentsImpl components;

    public ComponentsImplProxy(ComponentsImpl components) {
        this.components = components;
    }

    public void init(Bundle savedInstanceState,Object obj) {
        if (components instanceof Activity) {
            ButterKnife.bind((Activity) components);
        }else if(obj instanceof View){
            ButterKnife.bind(components, (View) obj);
        }
        recoverAndBeforeInfalter(savedInstanceState);
        initData();
        initEvent();
    }

    @Override
    public void beforeInit() {
        components.beforeInit();
    }

    @Override
    public void initData() {
        components.initData();
    }

    @Override
    public void initEvent() {
        components.initEvent();
    }

    @Override
    public void recoverAndBeforeInfalter(@Nullable Bundle savedInstanceState) {
        if (savedInstanceState == null) {
            return;
        }
        components.recoverAndBeforeInfalter(savedInstanceState);
    }

    @Override
    public int getLayoutId() {
        int layoutId = components.getLayoutId();
        if (layoutId == 0) {
            L.e("Activity或者是Fragment或者View不能没有layout id");
            throw new IllegalStateException("Activity或者是Fragment或者View不能没有layout id");
        }
        return layoutId;
    }

    /**
     * 释放
     */

    public void destroyComponents() {
        ButterKnife.unbind(components);
        if (components == null) {
            return;
        }
        if (components instanceof Activity) {
            if (!((Activity) components).isFinishing()) {
                ((Activity) components).finish();
            }
        }

        components = null;
    }
}

关于代理模式,大家请先去查看相关资料,简单来讲就是代理类拥有真实角色的引用,然后在代理类里面使用这个引用调用具体实现。我们这里需要注意的是init方法,他是的调用在实际中是在getLayoutId和beforeInit之后的,还可以做类似的判空,不用每一个Base类都去做。
这样子实现的好处就是一个是节省代码,一个是分类管理,易于变化。比如当我们的接口发生变化的时候,我们只是需要改动代理类的调用,而不管Base类的调用,这样子就可以实现单一原则。

具体的Base类

以一个BaseActivity 来讲,他是负责调用代理类的,接口的具体实现是有Base类的子类实现的。

public abstract class BaseActivity extends AppCompatActivity implements ComponentsImpl {
    private ComponentsImplProxy componentsImplProxy;
    protected LG BL;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        componentsImplProxy = new ComponentsImplProxy(this);
        int layoutId = componentsImplProxy.getLayoutId();
        componentsImplProxy.beforeInit();
        setContentView(layoutId);
        // 状态栏处理
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
            localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
        }
        BL = new LG(this.getClass());
        componentsImplProxy.init(savedInstanceState,null);
    }

    @Override
    protected void onStart() {
        super.onStart();
        BL.d("AppCompatActivity onStart");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        BL.d("AppCompatActivity onRestart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        BL.d("AppCompatActivity onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        BL.d("AppCompatActivity onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        BL.d("AppCompatActivity onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        BL.d("AppCompatActivity onDestroy");
        componentsImplProxy.destroyComponents();
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        BL.d("AppCompatActivity onLowMemory");
    }
}

然后具体子类的实现:

public class WelcomeActivity extends BaseActivity {
    @Override
    public void beforeInit() {
        requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//去掉信息栏
    }

    @Override
    public void initData() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent(WelcomeActivity.this,
                        GalleryMainActivity.class);
                startActivity(intent);
                finish();
            }
        }, 1500);
    }

    @Override
    public void initEvent() {

    }

    @Override
    public void recoverAndBeforeInfalter(@Nullable Bundle savedInstanceState) {

    }

    @Override
    public int getLayoutId() {
        return R.layout.activity_welcome;
    }


}

以后我们的具体子类就可以继承对应的Base类,这样子我们的项目就有了一个统一的规则,以后不论谁接手都会按照这个规则去做,项目维护起来也是比较的顺利。

我的公众号:
这里写图片描述
请大家关注,大家对于本文的建议也可以提出了指正,thanks。

<think>我们正在讨论的是Android系统中WindowManager的初始化过程。根据用户提供的引用,我们可以总结出一些关键点: 1. 引用[1]提到:在Activity的onResume生命周期后,会调用WindowManagerImpl的addView方法。这暗示了WindowManager的初始化与Activity生命周期有关。 2. 引用[2]说明:WindowManager继承自ViewManager接口,负责窗口管理。 3. 引用[3]指出:Window的添加、删除和更新最终都会通过IPC交给WindowManagerService处理。 4. 引用[4]提到:我们可以通过windowManager.getDefaultDisplay()获取屏幕参数,说明WindowManager在初始化后可以提供显示服务。 5. 引用[5]展示了应用启动过程中,AMS通过binder调用ActivityThread的bindApplication来初始化应用,这涉及到应用进程的初始化,可能包括WindowManager的初始化。 因此,WindowManager的初始化过程应该从系统启动和应用启动两个层面来看: - 系统层面:WindowManagerService(WMS)在系统启动时初始化。 - 应用层面:每个应用进程中的WindowManager(具体实现是WindowManagerImpl)在应用启动过程中初始化,并与WMS建立连接。 接下来,我们将详细分析这两个层面的初始化过程。 ### 一、系统层面:WindowManagerService的初始化 WindowManagerService(WMS)是系统服务,在Android系统启动过程中由SystemServer启动。 #### 1. **启动时机** 系统启动时,SystemServer会启动各种系统服务,包括WMS。具体流程如下: - SystemServer的`startBootstrapServices()`方法中启动ActivityManagerService(AMS)。 - 随后在`startOtherServices()`方法中启动WMS,并传入AMS等依赖。 引用源码(Android 14)中的关键步骤: ```java // SystemServer.java private void startOtherServices() { // ... WindowManagerService wm = null; // 创建WMS实例 wm = new WindowManagerService(context, inputManager, !mFirstBoot, mOnlyCore, new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager); // 将WMS添加到ServiceManager ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL); // 初始化WMS wm.systemReady(); // ... } ``` #### 2. **初始化关键步骤** - **构造WMS对象**:需要传入Context、InputManagerService等依赖。 - **注册Binder服务**:通过`ServiceManager.addService()`将WMS注册到ServiceManager,这样应用进程可以通过Binder调用WMS。 - **调用`systemReady()`**:在系统启动的最后阶段,通知WMS系统已准备就绪。 至此,WMS作为系统服务已初始化完成,等待应用进程的连接请求。 ### 二、应用层面:WindowManager的初始化 应用进程中的WindowManager是一个接口,其实现类是`WindowManagerImpl`。它的初始化与Activity的创建和启动密切相关。 #### 1. **应用进程初始化时创建WindowManagerGlobal** 每个应用进程有一个全局的`WindowManagerGlobal`单例,用于管理所有窗口。它在应用进程启动时初始化。 引用[5]提到:应用进程通过ActivityThread的`handleBindApplication`初始化。在这个过程中,会创建应用的ContextImpl,而ContextImpl中会包含WindowManager的实例。 #### 2. **Activity创建时关联WindowManager** 当Activity被创建时(例如,在`ActivityThread.performLaunchActivity()`中),会创建Activity的上下文(Context)和窗口(Window): - 创建PhoneWindow:每个Activity对应一个PhoneWindow。 - 创建WindowManagerImpl:通过PhoneWindow的`getWindowManager()`获取。 关键代码(ActivityThread.java): ```java // ActivityThread.java private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { // ... // 创建Activity实例 Activity activity = null; activity = mInstrumentation.newActivity(cl, component, r.intent); // 创建Application Application app = r.packageInfo.makeApplication(false, mInstrumentation); // 创建ContextImpl ContextImpl appContext = createBaseContextForActivity(r); // 关联WindowManager activity.attach(appContext, this, getInstrumentation(), r.token, /* ... */); // ... } // Activity.java final void attach(Context context, ...) { // 创建PhoneWindow mWindow = new PhoneWindow(this, window, activityConfigCallback); // 设置WindowManager mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE), ...); mWindowManager = mWindow.getWindowManager(); } ``` 在Activity的`attach()`方法中: 1. 创建PhoneWindow对象。 2. 通过Context获取系统服务`WindowManager`(即`WindowManagerImpl`实例),然后将其设置给PhoneWindow。 3. 从PhoneWindow中获取WindowManager(即`WindowManagerImpl`)并保存在Activity的成员变量中。 #### 3. **Context.getSystemService()获取WindowManager** `Context.getSystemService(Context.WINDOW_SERVICE)`返回的是`WindowManagerImpl`实例。这个实例是在应用进程初始化时创建的。 在ContextImpl(Context的实现类)中,会注册各种服务,包括WINDOW_SERVICE: ```java // ContextImpl.java @Override public Object getSystemService(String name) { return SystemServiceRegistry.getSystemService(this, name); } // SystemServiceRegistry.java static { // ... registerService(Context.WINDOW_SERVICE, WindowManager.class, new CachedServiceFetcher<WindowManager>() { @Override public WindowManager createService(ContextImpl ctx) { // 创建WindowManagerImpl实例 return new WindowManagerImpl(ctx.getDisplay()); } }); // ... } ``` 注意:这里创建的是`WindowManagerImpl`,它内部会持有当前Display(显示设备)的信息。 #### 4. **WindowManagerImpl与WMS的通信** 应用进程中的`WindowManagerImpl`只是一个代理,真正的窗口操作会通过Binder调用到系统进程的WMS。 例如,添加窗口时(`WindowManagerImpl.addView()`): ```java // WindowManagerImpl.java @Override public void addView(View view, ViewGroup.LayoutParams params) { // 委托给WindowManagerGlobal mGlobal.addView(view, params, mDisplay, mParentWindow); } // WindowManagerGlobal.java public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { // ... ViewRootImpl root = new ViewRootImpl(view.getContext(), display); root.setView(view, wparams, panelParentView); // ... } ``` 在`ViewRootImpl`的构造过程中,会通过`WindowSession`(一个Binder对象)与WMS建立连接: ```java // ViewRootImpl.java public ViewRootImpl(Context context, Display display) { // ... mWindowSession = WindowManagerGlobal.getWindowSession(); // ... } // WindowManagerGlobal.java public static IWindowSession getWindowSession() { // 通过Binder获取WMS的代理 IWindowManager windowManager = getWindowManagerService(); return windowManager.openSession(...); } ``` ### 三、总结 WindowManager的初始化分为两个层面: 1. **系统层面**:WMS在系统启动时由SystemServer初始化并注册到ServiceManager。 2. **应用层面**: - 应用进程启动时,在ActivityThread中初始化全局的`WindowManagerGlobal`。 - 每个Activity创建时,会创建PhoneWindow和WindowManagerImpl(通过Context.getSystemService()获取)。 - WindowManagerImpl内部通过`ViewRootImpl`与WMS通信,完成窗口的添加、更新和删除。 整个过程体现了Android系统的分层设计:应用进程的WindowManager作为客户端,通过Binder与系统进程的WMS交互,实现窗口管理。 ### 相关问题 1. WindowManagerService在系统启动过程中是如何初始化的? 2. 应用进程中的WindowManagerImpl如何与WMS通信? 3. Activity的WindowManager是如何创建的? 4. 如何通过WindowManager获取屏幕参数?</think>### Android WindowManager 初始化过程详解 WindowManager 是 Android 窗口系统的核心组件,负责管理应用程序窗口的创建、更新和销毁。其初始化过程涉及系统服务和应用进程的协同工作,以下是详细步骤: #### 一、系统服务层初始化(WindowManagerService) 1. **系统启动时创建** - 在 Android 系统启动阶段,`SystemServer` 进程会初始化 `WindowManagerService`(WMS) - 代码位置:`frameworks/base/services/java/com/android/server/SystemServer.java` ```java private void startOtherServices() { // 创建WMS实例 wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore); // 注册到ServiceManager ServiceManager.addService(Context.WINDOW_SERVICE, wm); // 初始化完成通知 wm.systemReady(); } ``` 2. **关键依赖注入** - WMS 初始化时需要注入: - `ActivityManagerService`(AMS):用于管理应用生命周期 - `InputManagerService`:处理输入事件分发 - `DisplayManagerService`:管理多显示器支持 - 通过 `ServiceManager` 获取这些服务的 Binder 代理 3. **核心功能初始化** - 创建 `WindowAnimator` 负责窗口动画 - 初始化 `SurfaceFlinger` 连接用于图形合成 - 建立 `DisplayContent` 管理屏幕层级关系 - 启动策略管理类 `PhoneWindowManager` #### 二、应用进程层初始化(WindowManagerImpl) 1. **应用启动时绑定** - 当应用进程启动时,AMS 通过 Binder 调用 `ActivityThread.bindApplication()` - 在 `handleBindApplication()` 中初始化应用级窗口管理组件[^5] ```java // ActivityThread.java private void handleBindApplication(AppBindData data) { // 创建应用的ContextImpl ContextImpl appContext = ContextImpl.createAppContext(this, data.info); // 初始化WindowManager全局实例 WindowManagerGlobal.initialize(); } ``` 2. **WindowManagerImpl 创建** - 通过 `Context.getSystemService(Context.WINDOW_SERVICE)` 获取实例 - 实际返回的是 `WindowManagerImpl` 对象(装饰器模式) ```java // SystemServiceRegistry.java registerService(Context.WINDOW_SERVICE, WindowManager.class, new CachedServiceFetcher<WindowManager>() { @Override public WindowManager createService(ContextImpl ctx) { return new WindowManagerImpl(ctx.getDisplay()); } }); ``` 3. **与 WMS 建立连接** - 首次添加窗口时通过 `ViewRootImpl` 建立连接 ```java // ViewRootImpl.java public void setView(View view, WindowManager.LayoutParams attrs) { // 获取WindowSession代理对象 mWindowSession = WindowManagerGlobal.getWindowSession(); // 向WMS添加窗口 mWindowSession.addToDisplay(...); } ``` #### 三、窗口添加流程(以 Activity 为例) 1. **Activity 启动阶段** - `ActivityThread.handleResumeActivity()` 触发窗口添加 ```java final void handleResumeActivity(IBinder token) { // 调用onResume() ActivityClientRecord r = performResumeActivity(token); // 获取WindowManager ViewManager wm = r.activity.getWindowManager(); // 添加DecorView wm.addView(decorView, layoutParams); } ``` 2. **IPC 调用过程** ```mermaid sequenceDiagram 应用进程->>ViewRootImpl: setView(decorView) ViewRootImpl->>IWindowSession: addToDisplay() IWindowSession->>WMS: addWindow() (Binder IPC) WMS-->>SurfaceFlinger: createSurface() SurfaceFlinger-->>WMS: SurfaceControl WMS-->>ViewRootImpl: 返回SurfaceControl ``` 3. **窗口管理关键对象** | 对象 | 作用 | 生命周期 | |------|------|----------| | `WindowToken` | 标识应用窗口组 | 应用存在期间 | | `WindowState` | 单个窗口状态管理 | 窗口存在期间 | | `SurfaceControl` | 图形表面控制 | 与窗口同生命周期 | #### 四、特殊场景处理 1. **多显示器支持** - 通过 `DisplayManager` 获取 `Display` 对象 - 调用 `WindowManager.getDefaultDisplay()` 获取主显示器参数[^4] ```java Display display = windowManager.getDefaultDisplay(); Point size = new Point(); display.getRealSize(size); // 获取屏幕实际分辨率 ``` 2. **窗口更新机制** - 调用 `WindowManager.updateViewLayout()` 触发 - 通过 `ViewRootImpl.scheduleTraversals()` 异步处理 - 最终调用 WMS 的 `relayoutWindow()` 更新窗口参数[^3] 3. **内存优化** - 应用退到后台时,WMS 自动销毁对应的 `Surface` - 通过 `TrimMemory` 回调释放窗口资源 - 低内存时自动销毁非活动窗口 ### 总结 WindowManager 的初始化是分层实现的: 1. **系统层**:`WindowManagerService` 在系统启动时初始化,作为窗口管理的核心 2. **应用层**:`WindowManagerImpl` 在应用启动时创建,通过 Binder IPC 与 WMS 通信 3. **窗口层**:通过 `ViewRootImpl` 管理具体窗口的生命周期,与 `SurfaceFlinger` 交互实现图形渲染 整个过程体现了 Android 系统的**分层架构**和**IPC设计**,确保了窗口管理的安全性和高效性[^1][^3]。 ### 相关问题 1. WindowManagerService 如何处理多窗口模式(分屏)? 2. ViewRootImpl 在窗口管理中扮演什么角色? 3. 如何通过 WindowManager 实现悬浮窗效果? 4. WindowManager 与 SurfaceFlinger 如何协作实现图形渲染?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值