拓展篇:如何获得AlarmManager对象
2012-05-09 15:20
246 查看
从AlarmManager的源码中可以看出,它只有一个访问权限为default的构造方法
那么,就只有它同包的类才能通过new的方法获得AlarmManager的实例,我们在自己的应用中是不能通过new这样的方法来得到它的实例的,也没有类似的getInstance()方法。
要想获得AlarmManager的实例,就必须通过Conetxt.getSystemService(Context.ALARM_SERVICE)的手段来获取。
而且,在一个Activity和一个Service中都可以试用Conetxt.getSystemService(Context.ALARM_SERVICE),因为Service和Activity都有相同的父类ContextWrapper。所有,必须先分析一下Context的继承体系,找出getSystemService()方法实际的位置和作用。
1、Context的简单分析
下面是Context的介绍
翻译:Context提供了关于应用环境全局信息的接口。它是一个抽象类,它的执行被Android系统所提供。它允许获取以应用为特征的资源和类型。同时启动应用级的操作,如启动Activity,broadcasting和接收intents。
查看Conetxt的源码:
可以发现大部分都是静态的常量字符串和抽象方法,只有少部分有实现,而getSystemService()也是一个抽象的方法。
2、ContextWrapper的简单分析
下面是ContextWrapper的成员变量和构造器:
Google API的介绍:
可以修改子类的行为,而不用修改原来的Context。
这是API的介绍,我翻译的不准确,不过大概可以理解:
先从字面意思来理解,ContextWrapper意思就是Context的包装类,也就是对Context的进一步的包装。就如果Integer对int的包装,
我们同样可以通过Integer实现对一个整形的各种操作。
可以看到ContextWrapper中只有一个访问权限为default的Context对象的引用mBase,
注意:这里的mBase只是一个引用,具体引用的对象还要根据传递进来的对象来确定,只要是Context对象的子类就行。
ContextWrapper重写了Context方法里面的所有方法,除了一个自己的构造器和get器,没有重新定义自己的方法。
而它重写的所有方法,几乎都一模一样,随便举几个例子:
改变一个Context对象(mBase)。也就是API中所说的:Context的代理实现,仅仅代表对另一个Context的所有请求
可以修改子类的行为,而不用修改原来的Context。
可以看到在ContextWrapper中也没有具体的实现,所以还要往下面继续的追踪。在看ContextWrapper的子类
3、ContextThemeWrapper的简单分析
ContextThemeWrapper里面的代码比较少。
看API的介绍:
也就是说,这个类主要是用来修改一个Context对象的风格。这也是为什么Service对象不是继承ContextThemeWrapper,而是继承它的父类ContextWrapper,因为Service不需要界面,当然无所谓风格。
不过,它依然重写了父类的getSystemService()方法:
可以看到,它的具体实现只针对一个LayoutInflater对象,对于其他的服务,依然调用的是mBase.getSystemService()方法。
所以,还要继续往下面看。看它的子类Activity
4、Activity的简单分析
Activity的作用就不说了,学Android应该都知道。
查看Activity的源码,很长哈,找到里面的getSystemService()方法,如下:
而他父类的getSystemService()方法,也只有LayoutInflater的实现,所以,仔仔细细的分析一遍,我们都没有发现getSystemService()方法中有我们所想要的AlarmManager()的
实现。
那么,从另一个角度,系统需要启动一个应用程序,那么,就必须要启动一个Activity,那么就必须需要实例化Activity对象。Activity对象的启动和实例化,都是由Android系统完成的。那么,Activity究竟是如何实例化的。Activity中并没有显示的构造方法,那么就只能来自父类ContextThemeWrapper了,ContextThemeWrapper有两个构造方法
显然,要想得到一个能够用于实际操作的Activity对象,会调用第二个构造方法,而这个构造方法又使用super(base),又会调用ContextWrapper的构造方法:
所以,可以明白,关键是这个实例化Activity传递的Context对象究竟是谁的Context。
最终发现,实例化Activity的Conetxt对象是ApplicationContext的对象,而ApplicationContext.java属于未开源的代码,
里面的getSystemService()方法的具体实现:
所以,纠结了一圈才发现,得到一个AlarmManager原本很简单,却被Google给隐藏起来了。现在就很好理解了,可以想到,在Service中,传递的也是ApplicationContext的Context对象,所以,在Activity和Service中都可以通过
getSystemService(name)来获得一个系统级的服务。
最后来个总结:
String serviceName=".....";
getSystemService(serviceName)的生命旅程:
1、首先Activity调用自己getSystemService():
2、如果不满足判断的条件,那么就会去调用父类的getSystemService():
3、在如果不满足判断的条件,就返回mBase.getSystemService(name),而mBase是一个ApplicationConetxt对象,那么就会去调用ApplicationConetxt的getSystemService()
方法:
就这样一步步的执行,知道找到为止。
AlarmManager(IAlarmManager service) { mService = service; }
那么,就只有它同包的类才能通过new的方法获得AlarmManager的实例,我们在自己的应用中是不能通过new这样的方法来得到它的实例的,也没有类似的getInstance()方法。
要想获得AlarmManager的实例,就必须通过Conetxt.getSystemService(Context.ALARM_SERVICE)的手段来获取。
而且,在一个Activity和一个Service中都可以试用Conetxt.getSystemService(Context.ALARM_SERVICE),因为Service和Activity都有相同的父类ContextWrapper。所有,必须先分析一下Context的继承体系,找出getSystemService()方法实际的位置和作用。
1、Context的简单分析
下面是Context的介绍
/** * Interface to global information about an application environment. This is * an abstract class whose implementation is provided by * the Android system. It * allows access to application-specific resources and classes, as well as * up-calls for application-level operations such as launching activities, * broadcasting and receiving intents, etc. */
翻译:Context提供了关于应用环境全局信息的接口。它是一个抽象类,它的执行被Android系统所提供。它允许获取以应用为特征的资源和类型。同时启动应用级的操作,如启动Activity,broadcasting和接收intents。
查看Conetxt的源码:
可以发现大部分都是静态的常量字符串和抽象方法,只有少部分有实现,而getSystemService()也是一个抽象的方法。
/** * 根据传递进来的名字,返回一个系统级应用的句柄。 * 注意:通过这种API获得的系统服务与这个context紧密结合在一起。一般情况下,不会在不同的context之间传递和共享这个系统级服务。( * 如Activities,Applications, Services, Providers等等) */ public abstract Object getSystemService(String name);Context中的getSystemService没有具体的实现,所以还要继续的看Conetxt的子类ContextWrapper。
2、ContextWrapper的简单分析
下面是ContextWrapper的成员变量和构造器:
public class ContextWrapper extends Context { Context mBase; public ContextWrapper(Context base) { mBase = base; } .......... }
Google API的介绍:
/** * Proxying implementation of Context that simply delegates all of its calls to * another Context. Can be subclassed to modify behavior without changing * the original Context. */翻译下:Context的代理实现,仅仅代表对另一个Context的所有请求
可以修改子类的行为,而不用修改原来的Context。
这是API的介绍,我翻译的不准确,不过大概可以理解:
先从字面意思来理解,ContextWrapper意思就是Context的包装类,也就是对Context的进一步的包装。就如果Integer对int的包装,
我们同样可以通过Integer实现对一个整形的各种操作。
可以看到ContextWrapper中只有一个访问权限为default的Context对象的引用mBase,
注意:这里的mBase只是一个引用,具体引用的对象还要根据传递进来的对象来确定,只要是Context对象的子类就行。
ContextWrapper重写了Context方法里面的所有方法,除了一个自己的构造器和get器,没有重新定义自己的方法。
而它重写的所有方法,几乎都一模一样,随便举几个例子:
//这是获得AssetManager的方法 @Override public AssetManager getAssets() { return mBase.getAssets(); } //这是获得PackageManager的方法 @Override public PackageManager getPackageManager() { return mBase.getPackageManager(); } // 这是获得系统级服务的方法 @Override public Object getSystemService(String name) { return mBase.getSystemService(name); }可以看到,所有的方法都是同一种模式:都是调用mBase对象中的方法,而mBase又是一个Context对象,所以,它是通过一个ContextWrapper对象
改变一个Context对象(mBase)。也就是API中所说的:Context的代理实现,仅仅代表对另一个Context的所有请求
可以修改子类的行为,而不用修改原来的Context。
可以看到在ContextWrapper中也没有具体的实现,所以还要往下面继续的追踪。在看ContextWrapper的子类
3、ContextThemeWrapper的简单分析
ContextThemeWrapper里面的代码比较少。
看API的介绍:
/** * A ContextWrapper that allows you to modify the theme from what is in the * wrapped context. */翻译:允许你修改一个你包装的context对象的风格。
也就是说,这个类主要是用来修改一个Context对象的风格。这也是为什么Service对象不是继承ContextThemeWrapper,而是继承它的父类ContextWrapper,因为Service不需要界面,当然无所谓风格。
不过,它依然重写了父类的getSystemService()方法:
@Override public Object getSystemService(String name) { if (LAYOUT_INFLATER_SERVICE.equals(name)) { if (mInflater == null) { mInflater = LayoutInflater.from(mBase).cloneInContext(this); } return mInflater; } return mBase.getSystemService(name); }
可以看到,它的具体实现只针对一个LayoutInflater对象,对于其他的服务,依然调用的是mBase.getSystemService()方法。
所以,还要继续往下面看。看它的子类Activity
4、Activity的简单分析
Activity的作用就不说了,学Android应该都知道。
查看Activity的源码,很长哈,找到里面的getSystemService()方法,如下:
@Override public Object getSystemService(String name) { if (getBaseContext() == null) { throw new IllegalStateException( "System services not available to Activities before onCreate()"); } if (WINDOW_SERVICE.equals(name)) { return mWindowManager; } else if (SEARCH_SERVICE.equals(name)) { ensureSearchManager(); return mSearchManager; } return super.getSystemService(name); }可以发现,Activity重写了父类的Activity,其中只有WindowManager和SearchManager的实现,其余的就是super.getSystemService()。
而他父类的getSystemService()方法,也只有LayoutInflater的实现,所以,仔仔细细的分析一遍,我们都没有发现getSystemService()方法中有我们所想要的AlarmManager()的
实现。
那么,从另一个角度,系统需要启动一个应用程序,那么,就必须要启动一个Activity,那么就必须需要实例化Activity对象。Activity对象的启动和实例化,都是由Android系统完成的。那么,Activity究竟是如何实例化的。Activity中并没有显示的构造方法,那么就只能来自父类ContextThemeWrapper了,ContextThemeWrapper有两个构造方法
public ContextThemeWrapper() { super(null); } public ContextThemeWrapper(Context base, int themeres) { super(base); mBase = base; mThemeResource = themeres; }
显然,要想得到一个能够用于实际操作的Activity对象,会调用第二个构造方法,而这个构造方法又使用super(base),又会调用ContextWrapper的构造方法:
public ContextWrapper(Context base) { mBase = base; }
所以,可以明白,关键是这个实例化Activity传递的Context对象究竟是谁的Context。
最终发现,实例化Activity的Conetxt对象是ApplicationContext的对象,而ApplicationContext.java属于未开源的代码,
public class ApplicationContext extends Context
里面的getSystemService()方法的具体实现:
public Object getSystemService(String name) { if("window".equals(name)) return WindowManagerImpl.getDefault(); if("inflate".equals(name)) return new WidgetInflate(this); if("alarm".equals(name)) return new AlarmManager(); if("power".equals(name)) return getPowerManager(); if("notification".equals(name)) return getNotificationManager(); if("keyguard".equals(name)) return new KeyguardManager(); if("location".equals(name)) return getLocationManager(); else return null; }
所以,纠结了一圈才发现,得到一个AlarmManager原本很简单,却被Google给隐藏起来了。现在就很好理解了,可以想到,在Service中,传递的也是ApplicationContext的Context对象,所以,在Activity和Service中都可以通过
getSystemService(name)来获得一个系统级的服务。
最后来个总结:
String serviceName=".....";
getSystemService(serviceName)的生命旅程:
1、首先Activity调用自己getSystemService():
@Override public Object getSystemService(String name) { if (getBaseContext() == null) { throw new IllegalStateException( "System services not available to Activities before onCreate()"); } if (WINDOW_SERVICE.equals(name)) { return mWindowManager; } else if (SEARCH_SERVICE.equals(name)) { ensureSearchManager(); return mSearchManager; } return super.getSystemService(name); }
2、如果不满足判断的条件,那么就会去调用父类的getSystemService():
@Override public Object getSystemService(String name) { if (LAYOUT_INFLATER_SERVICE.equals(name)) { if (mInflater == null) { mInflater = LayoutInflater.from(mBase).cloneInContext(this); } return mInflater; } return mBase.getSystemService(name); }
3、在如果不满足判断的条件,就返回mBase.getSystemService(name),而mBase是一个ApplicationConetxt对象,那么就会去调用ApplicationConetxt的getSystemService()
方法:
public Object getSystemService(String name) { if("window".equals(name)) return WindowManagerImpl.getDefault(); if("inflate".equals(name)) return new WidgetInflate(this); if("alarm".equals(name)) return new AlarmManager(); if("power".equals(name)) return getPowerManager(); if("notification".equals(name)) return getNotificationManager(); if("keyguard".equals(name)) return new KeyguardManager(); if("location".equals(name)) return getLocationManager(); else return null; }
就这样一步步的执行,知道找到为止。
相关文章推荐
- 【问题】如何获得报表中某对象的值与程序进行交互?
- 如何获得SQLSERVER2000指定对象的权限列表?
- js的Object对象如何访问中间有 . 点号的属性(键),获得其值?
- 【问题】如何获得报表中某对象的值与程序进行交互?
- 简述c++中string对象的内存分配策略?如何获得其可存储的最大字节
- 如何获得div对象的绝对坐标
- RevitAPI: 如何获得链接CAD里面对象的图层信息?
- Spring如何获得容器对象
- 浅谈Java如何将字符串转成Json对象以及从Json对象中获得相应的值
- DWR如何获得返回对象
- 揭示同步块索引(中):如何获得对象的HashCode 转载
- 如何从Sring中获得json对象 jsonObject用法
- Java中如何由枚举常量的ordinal值获得枚举常量对象
- 元素ID是个字符串变量,如何用jquery选择器获得这个对象?
- 如何获得servletConfig对象和servletContext对象以及通过这两个对象获得初始化参数
- 如何获得Context实例化对象
- JSF如何在后台获得前台页面的标签对象
- Java中如何由枚举常量的ordinal值获得枚举常量对象
- DWR如何获得返回对象 list Map Set list.add(JavaBean)
- 如何获得struts2的request response session 对象