Android 源码系列之<四>从源码的角度深入理解LayoutInflater.Factory之主题切换(上)

本文探讨Android中实现主题切换的源码角度分析,重点关注LayoutInflater.Factory的作用。通过研究QQ和网易新闻等应用的夜间模式功能,了解到主题切换主要涉及背景图片、颜色、字体的替换。首先介绍了LayoutInflater的重要性,它是将XML布局转换为View的必备工具。文中列举了获取LayoutInflater实例的三种常见方式,并预告将从源码层面解析主题切换的实现细节。
摘要由CSDN通过智能技术生成

        转载请注明出处:http://blog.csdn.net/llew2011/article/details/51252401

        现在越来越多的APP都加入了主题切换功能或者是日间模式和夜间模式功能切换等,这些功能不仅增加了用户体验也增强了用户好感,众所周知QQ和网易新闻的APP做的用户体验都非常好,它们也都有日间模式和夜间模式的主题切换功能。体验过它们的主题切换后你会发现大部分效果是更换相关背景图片、背景颜色、字体颜色等来完成的,网上这篇文章对主题切换讲解的比较不错,今天我们从源码的角度来学习一下主题切换功能,如果你对这块非常熟悉了,请跳过本文(*^__^*) …

        在开始讲解主题切换之前我们先看一下LayoutInflater吧,大家都应该对LayoutInflater的使用非常熟悉了(如果你对它的使用还不是很清楚请自行查阅)。LayoutInflater的使用场合非常多,常见的比如在Adapter的getView()方法中,在Fragment中的onCreateView()中使用等等,总之如果我们想要把对应的layout.xml文件渲染成对应的View层级视图,离开LayoutInflater是不行的,那么我们如何获取LayoutInflater实例并用其来渲染成对应的View实例对象呢?一般有以下几种方式:

  1. 调用Context.getSystemService()方法
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rootView = inflater.inflate(R.layout.view_layout, null);
  2. 直接使用LayoutInflater.from()方法
    LayoutInflater inflater = LayoutInflater.from(context);
    View rootView = inflater.inflate(R.layout.view_layout, null);
  3. 在Activity下直接调用getLayoutInflater()方法
    LayoutInflater inflater = getLayoutInflater();
    View rootView = inflater.inflate(R.layout.view_layout, null);
  4. 使用View的静态方法View.inflate()
    rootView = View.inflate(context, R.layout.view_layout, null);
        以上4种方式都可以渲染出一个View实例出来但也都是借助LayoutInflater的inflate()方法来完成的,我们先看一下方式2中LayoutInflater.from()是怎么做的,代码如下:
/**
 * Obtains the LayoutInflater from the given context.
 */
public static LayoutInflater from(Context context) {
    LayoutInflater LayoutInflater =
            (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (LayoutInflater == null) {
        throw new AssertionError("LayoutInflater not found.");
    }
    return LayoutInflater;
}
        LayoutInflater.from()方法只不过是对方式1的一层包装,最终还是通过调用Context的getSystemService()方法获取到LayoutInflater实例对象,然后通过返回的LayoutInflater实例对象调用其inflate()方法来完成对xml布局文件的渲染并生成相应的View对象。通过和方式1对比你会发现,这两种方式中的Context如果是相同的那么获取的LayoutInflater对象应该是同一个。然后我们在看一下方式3中的实现部分,方式3是在Activity中直接调用Activity的getLayoutInflater()方法,源码如下:
/**
 * Convenience for calling
 * {@link android.view.Window#getLayoutInflater}.
 */
public LayoutInflater getLayoutInflater() {
    return getWindow().getLayoutInflater();
}
        通过源码发现Activity的getLayoutInflater()方法辗转调用到了getWindow()的getLayoutInflater()方法,getWindow()方法返回一个Window类型的对象,其中Window为抽象类在Android中该类的实现类是PhoneWindow,也就是说getWindow().getLayoutInflater()方法最终调用的是PhoneWindow的getLayoutInflater()方法,我们看一下PhoneWindow类中该方法的实现过程,代码如下:
/**
 * Return a LayoutInflater instance that can be used to inflate XML view layout
 * resources for use in this Window.
 *
 * @return LayoutInflater The shared LayoutInflater.
 */
@Override
public LayoutInflater getLayoutInflater() {
    return mLayoutInflater;
}
        在PhoneWindow类中直接返回了mLayoutInflater对象,那么mLayoutInflater是在何时何地完成初始化的呢?我们继续查看mLayoutInflater的初始化在哪完成的,通过查看代码发现是在PhoneWindow的构造方法中完成初始化的,代码如下:
public PhoneWindow(Context context) {
    super(context);
    mLayoutInflater = LayoutInflater.from(context);
}
        我们暂且不关心PhoneWindow是何时何地完成初始化的,我们只关心mLayoutInflater的初始化也是直接调用LayoutInflater.from()方法来完成的,这种方式和方式2是一样的,都是借助传递进来的context调用其getSystemService()方法获取到LayoutInflater实例,也就是说只要PhoneWindow中传递进来的context和方式1、方式2是相同的,那么可以确定获取到的mLayoutInflat
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值