1.全局获取Context
- Android提供了一个Application 类,每当应用程序启动的时候,系统就会自动将这个类进行初始化。所以首先定制一个自己的Application 类,以便于管理程序内一些全局的状态信息。自定义类需要继承Appllication
- 接下来告知系统,程序启动的时候应该初始化MyApplication 类, 而不是默认的Application 类
- 接下来项目的任何地方调用context,调用方法如下:
MyApplication.getContext()
- 我们已经配置过application,但是又想使用LitePal的context:
<application android: name="org. itepal.LitePaLApplication" </ application>
LitePal的解决办法是在Application中调用LitePal的初始化方法:
2.使用Intent传递对象
2.1 传递普通数据
MainActivity:
Main2Activity:
2.2 传递自定义对象
2.2.1 Serializable传输对象数据
Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对
象可以在网络上进行传输,也可以存储到本地。序列化的方法让数据类去实现Serializable接口
- 新建对象类:
- 封装、发送数据
- 接收打印数据
2.2.2 Parcelable传输对象数据
使用Parcelable也可以实现相同的效果,不过不同于将对象进行序列化,Parcelable 方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型
- 继承接口,实现对象类
- 重写该对象类
- 封装、发送数据和S方法一样
- 接收对象,写出数据
3.定制日志工具
目的:自由控制日志的打印,当程序处于开发阶段就让日志打印出来,程序上线之后把日志屏蔽掉
4.创建定时任务
Android中的定时任务一般有两种实现方式,一种是使用Java API里提供的Timer类,一种
是使用Android的Alarm机制。这两种方式在多数情况下都能实现类似的效果,但Timer有一个明显的短板,它并不太适用于那些需要长期在后台运行的定时任务。为了能让电池
更加耐用,每种手机都会有自己的休眠策略,Android 手机就会在长时间不操作的情况下自动让CPU进入到睡眠状态,这就有可能导致Timer中的定时任务无法正常运行。而Alarm则具有唤醒CPU的功能,它可以保证在大多数情况下需要执行定时任务的时候CPU都能正常工作。需要注意,唤醒CPU不等于唤醒屏幕
4.1 Alarm机制
long triggerAtTime = System.currentTimeMillis() + 3 * 1000;
manager.set(AlarmManager.RTC_WAKEUP, triggerAtTime, pendingIntent);
第一个参数是一个整型参数,用于指定AlarmManager 的工作类型,有4种值可选,分别是ELAPSED_REALTIME、ELAPSED_REALTIME_WAKEUP、RTC 和RTC_WAKEUP。ELAPSED_REALTIME 表示让定时任务的触发时间从系统开机开始算起,但不会唤醒CPU。ELAPSED_REALTIME_WAKEUP 同样表示让定时任务的触发时间从系统开机开始算起, 但会唤醒CPU。 RTC 表示让定时任务的触发时间从1970年1月1日0点开始算起, 但不会唤醒CPU。RTC_WAKEUP 同样表示让定时任务的触发时间从1970年1月1日0点开始算起,但会唤醒CPU。使用SystemClock.elapsedRealtime() 方法可以获取到系统开机至今所经历时间的毫秒数,使用System.currentTimeMillis() 方法可以获取到1970年1月1日0点至今所经历时间的毫秒数。
第二个参数就是定时任务触发的时间, 以毫秒为单位。
如果第一个参数使用的是ELAPSED_REALTIME 或ELAPSED_REALTIME_WAKEUP , 则这里传入开机至今的时间再加上延迟执行的时间。 如果第一个参数使用的是RTC 或RTC_WAKEUP , 则这里传入1970年1月1日0点至今的时间再加上延迟执行的时间。
第三个参数是一个PendingIntent,调用getService() 方法或者getBroadcast() 方法来获取一个能够执行服务或广播的PendingIntent。这样当定时任务被触发的时候,服务的onStartCommand() 方法或广播接收器的onReceive() 方法就可以得到执行。
开启服务:
服务的函数实现:
先是在onStartCommand() 方法中开启了一个子线程,在这里执行具体的逻辑操作。之所以要在子线程里执行逻辑操作,是因为逻辑操作也是需要耗时的,如果放在主线程里执行可能会对定时任务的准确性造成轻微的影响。
创建线程之后使用Alarm机制,先是获取到了AlarmManager的实例, 然后定义任务的触发时间,再使用PendingIntent指定处理定时任务的服务,最后调用set() 方法完成设定。一旦启动了Service,就会在onStartCommand() 方法里设定一个定时任务,这样在设置一段时间后将会再次启动Service,从而也就形成了一个永久的循环,如果要求Alarm任务的执行时间必须准确无误,AlarmManager的setExact() 方法来替代set() 方法
4.2 Doze模式
当用户的设备是Android 6.0或以上系统时,如果该设备未插接电源且屏幕关闭了一段时间之后,就会进入到Doze模式。在Doze模式下,系统会对CPU、网络、Alarm等活动进行限制,从而延长了电池的使用寿命。系统并不会一直处于Doze模式, 而是会间歇性地退出Doze模式一小段时间, 在这段时间中, 应用就可以去完成它们的同步操作、 Alarm任务
Doze模式下有哪些功能会受到限制:
网络访问被禁止,系统忽略唤醒CPU或者屏幕操作,系统不再执行WIFI扫描。
系统不再执行同步服务,Alarm任务将会在下次退出Doze模式的时候执行。
在Doze模式下,我们的Alarm任务将会变得不准时。
如果要求Alarm任务即使在Doze模式下也必须正常执行
调用AlarmManager的setAndAllowWhileIdle()或setExactAndAllowWhileIdle() 方法代替set方法就能让定时任务即使在Doze模式下也能正常执行了
5. 多窗口模式
5.1生命周期
- 启动第一个项目MaterialTest
- 进入多窗口模式,之前的活动实现重建,并停留在暂停状态
- 多窗口模式下选择打开另一个程序
- 然后操作第一个程序
在多窗口模式下,用户仍然可以看到处于暂停状态的应用,那么像视频播放器之类的应用在此时就应该能继续播放视频才对。因此,我们最好不要在活动的onPause( )方法中去处理视频播放器的暂停逻辑,而是应该在onStop( )方法中去处理,并且在onStart()方法恢复视频的播放。
针对于进入多窗口模式时活动会被重新创建, 如果你想改变这一默认行为, 可以在
AndroidManifest.xml中对活动进行如下配置:
加入了这行配置之后,不管是进入多窗口模式,还是横竖屏切换,活动都不会被重新创建, 而是会将屏幕发生变化的事件通知到Activity的onConfigurationChanged() 方法当中。 因
此,如果想在屏幕发生变化的时候进行相应的逻辑处理,那么在活动中重写onConfigurationChanged() 方法即可。
5.2 禁用多窗口模式
targetSDKVersion>=24:
在AndroidManifest.xml的< application>或< activity> 标签中加入如下属性:android:resizeableActivity=["true" | "false"]
,true表示支持多窗口应用,false表示不支持,如果不配置,默认为true
targetSDKVersion<24:
如果项目指定的targetSdkVersion低于24,并且活动是不允许横竖屏切换的, 那么该应用也将不支持多窗口模式,portrait 表示活动只支持竖屏, landscape 表示活动只支持横屏
配置要求,前者只支持竖屏,后者只支持横屏:
android:screenOrientation=[“portrait” | “landscape”]
6.Lamda表达式
Lambda 表达式本质上是一种匿名方法, 它既没有方法名, 也即没有访问修饰符和返回值类型, 如果想要在Android项目中使用Lambda表达式或者Java 8的其他新特性, 首需要在app/build.gradle中添加如下配置:
android {
defaultConfig {...
jackOptions.enabled = true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}