1.使用Intent传递对象
使用Intent来传递对象通常有两种实现方式:Serializable和Parcelable。
Serializable是序列化的意思,标示将一个对象转换成可存储或可传输的状态,序列化后的对象可以在网络上进行传输也可以存储到本地,只需要让一个类去实现Serializable这个接口。可通过getSerialzableExtra()方法来获取通过参数传递过来的序列化对象。
Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型。首先实现Parcelable接口,重写describeContents()和writeToParcel()两个方法,describeContents()方法直接返回0,而writeToParcel()方法中调用writexxx()将类中字段一一写出,创建一个CREATOR常量,创建Parcelable.Creator接口的一个实现,重写createFromParcel()和newArray()两个方法,在createFromParcel()方法中读取写出的字段,并创建一个对象进行返回,newArray()方法中new出一个实例的数组,并使用方法中传入的size作为数组的大小就可以。可通过getParcelableExtra()方法来获取传递过来的对象。
Serializable的方式较为简单,由于会把整个对象进行序列化,效率会比Parcelabel方式低一些,推荐使用Parcelable的方式来实现Intent传递对象的功能。
2.创建定时任务
Android中的定时任务一般有两种实现方式,一种是使用Java API里提供的Timer类,一种是使用Android的Alarm机制。Timer又一个明显的短板,它不太适合那些需要长期在后台运行的定时任务,为了让电池更加耐用,每种手机都有自己的休眠策略,Android手机在长时间不操作的情况下自动让CPU进入睡眠状态,这就有可能导致Timer中的定时任务无法正常运行。而Alarm则具有唤醒CPU的功能,它可以保证在大多数情况下需要执行定时任务的时候CPU都能正常工作。
设定一个任务10s后执行:
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
long triggerAtTime = SystemClock.elapsedRealtime() + 10 * 1000;
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,peddingIntent);
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
long triggerAtTime = System.currentTimeMillis() + 10 * 1000;
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,peddingIntent);
第一个参数用于指定AlarmManager的工作类型,有四种类型:
AlarmManager.ELAPSED_REALTIME :表示让定时任务的触发时间从系统开机开始算起,但不会唤醒CPU。
AlarmManager.ELAPSED_REALTIME_WAKEUP:表示让定时任务的触发时间从系统开机开始算起,但会唤醒CPU。
AlarmManager.RTC:表示让定时任务的触发时间从1970年1月1日0点开始算起,但不会唤醒CPU。
AlarmManager.RTC_WAKEUP:表示让定时任务的触发时间从1970年1月1日0点开始算起,但会唤醒CPU。
SystemClock.elapsedRealtime()方法可以获取到系统开机至今所经历时间的毫秒数,使用System.currentTimeMills()方法可以获取1970年1月1日0点至今所经历时间的毫秒数。
第二个参数是定时任务触发的时间,以毫秒为单位,如果第一个参数使用的是ELAPSED_REALTIME或ELAPSED_REALTIME_WAKEUP,这里传入开机至今的时间再加上延迟执行的时间。如果第一个参数使用的是RTC或者RTC_WAKEUP,这里传入的是1970年1月1日0点至今的时间再加上延迟执行的时间。
第三个参数是一个PendingIntent,我们一般用getService()方法或者getBroadcast()方法来获取一个能够执行服务或广播的PendingIntent,这样当定时任务被触发的时候,服务的onStartCommand()方法或广播接收器的onReceive()方法就可以执行。
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
Log.d("test","do something");
}
}).start();
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
long triggerAtTime = SystemClock.elapsedRealtime() + 3 * 1000;
Intent i = new Intent(this,MyService.class);
PendingIntent pi = PendingIntent.getService(this,0,i,0);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pi);
return super.onStartCommand(intent, flags, startId);
}
Android4.4后,Alarm任务的触发时间会变得不准确,可用AlarmManager的setExact()方法来替代set()方法。3.Doze模式
Android6.0系统中,谷歌加入了一个全新的Doze模式,可以极大幅度地延长电池的寿命。如果用户的设备是Android6.0或以上系统该设备未插电源,处于静止状态,且屏幕关闭了一段时间后,就会进入Doze模式,在Doze模式下,系统化会对CPU,网络,Alarm等活动进行限制,从而延长电池的使用寿命。
4.多窗口编程模式
Android7.0系统中引入多窗口模式,允许我们在同一个屏幕中同时打开两个应用程序。
5.Lambda表达式
Java8中的新特性Lambda表达式,本质上是一种匿名方法,它既没有方法名,也没有访问修饰符和返回值类型,用它来编写代码将会更加简洁和易读。凡是只有一个待实现方法的接口,都可以使用Lambda表达式的写法。
// Java 8之前:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Before Java8, too much code for too little to do");
}
}).start();
//Java 8方式:
new Thread( () -> System.out.println("In Java8, Lambda expression rocks !!") ).start();