Android提供了一个Application类,每当应用程序启动的时候,系统就会自动把这个类进行初始化。我们可定制一个自己的Application类,用于获取全局Context
示例:
1.创建Application的子类对象,提供获取content的方法
import android.app.Application;
import android.content.Context;
public class MyApplication extends Application {
private static Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
//提供getContext()方法
public static Context getContext(){
return context;
}
}
2.在AndroidManifest.xml文件的application标签下指定,告知系统启动的是MyApplication,而不是默认的Application
<application
android:name=".MyApplication"
......
</application>
问题:为了让LitePal正常工作,必须要配置
<application
android:name="org.litepal.LitePalApplication"
......
</application>
这样配置之后,LitePal就可在内部自动获取到Context了。但是这样既无法配置MyApplication了,因为一个项目只能配置一个Application
解决办法:在我们自己的Application中调用LitePal的初始化方法就行
public class MyApplication extends Application {
private static Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
LitePal.initialize(context);
}
//提供getContext()方法
public static Context getContext(){
return context;
}
}
平时我们在用Intent传递数据时都用的putExtra()方法,但是当我们要传递的数据是自定义对象时,无法传递。实现方法如下:
序列化的意思,表示吧一个对象转换成可储存或可传输的状态,序列化后的对象可以在网络上传输,也可储存到本地
是一个接口,用时直接实现接口就可
class Person implements Serializable{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
发送:
Person person = new Person();
person.setAge(12);
person.setName("dag");
Intent intent = new Intent(MainActivity.this,MainActivity2.class);
intent.putExtra("person_data",person);
startActivity(intent);
接收:(注意:与原来的接收不同)
Intent intent = getIntent();
Person person = (Person)intent.getSerializableExtra("person_data");
它的实现原理是将一个完整的对象进行分解,分解后的每一部分都是Intent所支持的数据类型
class people implements Parcelable{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//直接返回0
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
//调用Parcel的writeXXX方法,吧类中的字段一一写出
dest.writeString(name);
dest.writeInt(age);
}
public static final Parcelable.Creator<people> CREATOR = new Parcelable.Creator<people>(){
@Override
public people createFromParcel(Parcel source) {
//读取刚才写出的name和age字段,读取顺序一定要和写入的完全相同
people people1 = new people();
people1.name = source.readString();
people1.age = source.readInt();
return people1;
}
@Override
public people[] newArray(int size) {
return new people[size];
}
};
}
发送:
people people1 = new people();
people1.setAge(12);
people1.setName("134455");
Intent intent1 = new Intent(MainActivity.this,MainActivity2.class);
intent.putExtra("people_data",person);
startActivity(intent);
接收:(注意:与原来的接收不同)
Intent intent = getIntent();
people people1 = (people) intent.getParcelableExtra("people_data");
目的:自由的控制日志的打印
示例:
class LogUtil{
public static final int VERBOSE = 1;
public static final int DEBUG = 2;
public static final int INFO = 3;
public static final int ERROR = 5;
public static final int WARN = 4;
public static final int NOTHING = 6;
public static int level = VERBOSE;
public static void v(String tag,String msg){
if(level <= VERBOSE)
Log.v(tag,msg);
}
public static void d(String tag,String msg){
if(level <= DEBUG)
Log.d(tag,msg);
}
public static void i(String tag,String msg){
if(level <= INFO)
Log.i(tag,msg);
}
public static void w(String tag,String msg){
if(level <= WARN)
Log.w(tag,msg);
}
public static void e(String tag,String msg){
if(level <= ERROR)
Log.e(tag,msg);
}
}
之后只需要修改level变量,就可控制打印情况
Android中的定时任务一般有两种实现方式,一种是Java API里的Timer类,一种是Android的Alarm机制
Timer并不太实用于那些需要长期在后台运行的定时任务,当长时间时,CPU进入到睡眠状态,可能导致Timer的定时任务无法正常运行
可以保证大多数情况下需要执行定时任务时CPU都能正常工作
如下是一个长时间在后台定时运行的服务
public class LongRuningService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
/*
一旦启动LongRuningService就会在onStartCommand中执行一个定时任务,
这样一个小时后将在此启动LongRuningService,形成循环
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
//执行具体的操作逻辑
}
}).start();
//获取AlarmManager对象
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
int anHour = 60*60*1000;
Long l = System.currentTimeMillis();
//SystemClock.elapsedRealtime()获取开机至今的毫秒数
//System.currentTimeMillis() 获取1970年 一月一日0点至今所经历的毫秒数
Long triggerAtTime = SystemClock.elapsedRealtime()+anHour;
Intent intent1 = new Intent(this,LongRuningService.class);
PendingIntent pendingIntent = PendingIntent.getService(this,0,intent1,0);
//设置定时任务
manager.set(AlarmManager.RTC_WAKEUP,triggerAtTime,pendingIntent);
/*三个参数:
第一个是整型参数用于指定AlarmManager的工作类型
第二个:触发时间
第三个是 PendingIntent
*/
return super.onStartCommand(intent,flags,startId);
}
}
AlarmManager的工作类型 | 说明 |
---|---|
ELAPSED_REALTIME | 让定时任务从系统开机开始算起,但不会唤醒CPU |
ELAPSED_REALTIME_WAKEUP | 让定时任务从系统开机开始算起,唤醒CPU |
RTC | 让系统任务从1970年一月一日0点开始算起,但不会唤醒CPU |
RTC_WAKEUP | 让系统任务从1970年一月一日0点开始算起,唤醒CPU |
注:对于不同的工作类型,要选择不同的时间
如果你要求Alarm任务的执行时间必须准确无误,应用setExact()方法替换set()方法
当用户设备是Android 6.0 或以上系统时,如果未插接电源,且屏幕关闭了一段时间之后就会进入到Doze模式
在该模式下,系统会对CPU,网络,Alarm等活动进行限制,从而延长电池的使用寿命
当然,它不会一直处于该模式,而是会间隙性的退出Doze模式一小段时间,在这段时间中去完成同步操作,Alarm任务
注:Doze模式下,Alarm任务就会变的不准时,解决方案
吧set()方法换成setExactAndAllowWhileIdle()或setAndAllowWhileIdle()方法就可让定时任务在Doze模式下也可正常执行
即我们常见的分屏操作,在该模式下活动会有一个重新创建的过程,如果操作一个程序,另一个程序会进入暂停状态(onPause)
如果你想改变进入多窗口模式活动被重新创建,可添加如下配置
<activity android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize|screenLayout">
.....
</activity>
<application
....
android:resizeableActivity="false">
.....
</application>
true表示支持,false表示不支持,默认是支持
android studio 中的配置
1.app的build文件下配置好
jackOptions{
enabled true
}
compileOptions{
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
retrolambda {
//指定将源码编译的级别,使用下列代码,会将代码编译到兼容1.6的字节码格式
javaVersion JavaVersion.VERSION_1_6
}
2.项目build文件下也要加上配置
apply plugin: 'me.tatarka.retrolambda'//lambda
dependencies {
classpath 'com.android.tools.build:gradle:3.1.3'
classpath 'me.tatarka:gradle-retrolambda:3.7.0' //lambda
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
剩下的使用和java使用方法一样
Lambda表达式