八、lambda表达式这个表达式是JAVA8的新特性,我们直接在后面完整的Demo中使用,用到的时候再具体的说明
获取全局Context
这里我们考虑这样一个问题,我们再一个类中进行了一些异步操作,完了之后我们需要一个Toast提示,这时候我们需要Context,那我们有那么获取Context。
首先就有这样一种,我们直接在初始化这个类的时候传递一个Context,的确这样是能解决问题的,但这不是最好的解决问题的办法,最好的办法是我们获取一个全局的Context,下面我们总结如何获取一个全局的Context。
packagecom.example.skotc.servicedemo;importandroid.app.Application;importandroid.content.Context;/***Createdbyskotcon2018/8/20.*/publicclassMyApplicationextendsApplication{privatestaticContextcontext;@OverridepublicvoidonCreate(){super.onCreate();context=getApplicationContext();}publicstaticContextgetContext(){returncontext;}}
上面的代码我们就创建了一个MyApplication继承自Application,然后再以后的使用中我们就可以直接调用这个方法得到全局的Context,MyApplication.getContext()方法获取得到Context。
使用Intent传递对象
Intent相信我们都比较熟悉了,我们可以使它来启动活动,发送广播,启动广播等,在进行上述操作的时候,我们还可以在Intent中添加一些附加数据,已达到传值的效果,比如我们见过的调用putExtra(键,值)方法来添加要传递的数据,之后通过调用getIntent().getStringExtra(键)来获取我们传递的值,通过这种方法我们能传递的对象类型是有限的,也就常见的类型,那我们有没有想过,要是需要专递的是一个自定义的对象的时候呢,我们该怎样做?
下面我们就讨论一下这个问题:
1、Serializable方式(序列化)
Serializable是序列化的意思,表示将一个对象转换成可存储或者可传输的状态,序列化后的对象可以在网络上进行传输,也可以存储在本地,至于序列化的方法也是很简单,只需要让一个类去实现Serializable接口就可以。
比如我们实现了一个person类,让它实现Serializable接口:
classpersonimplementsSerializable{privateStringname;privateintage;publicvoidsetName(Stringname){this.name=name;}publicvoidsetAge(intage){this.age=age;}publicStringgetName(){returnname;}publicintgetAge(){returnage;}}
接下来我们看看这个自定义对象的传递以及获取:
personzhangxu=newperson();zhangxu.setAge(18);zhangxu.setName("tiancia");//传递Intentintent=newIntent(ServiceMainActivity.this,SecondActivity.class);intent.putExtra("person",zhangxu);startActivity(intent);//获取personzhangxu2=(person)getIntent().getSerializableExtra("person");
一句话总结:我们之所以能将我们自定义的类在Intent中传递就是因为我们自定义为类实现了Serializable接口。
Parcelable
Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都将是Intent所支持的数据类型,这样也就实现传递对象的功能。
接下来我们修改我们的额person类,修改这个类的注意事项我们在代码中都有加注释
/***实现Parcelable接口*就要重写里面的两个方法*describeContents*writeToParcel***/classpersonimplementsParcelable{privateStringname;privateintage;publicvoidsetName(Stringname){this.name=name;}publicvoidsetAge(intage){this.age=age;}publicStringgetName(){returnname;}publicintgetAge(){returnage;}@OverridepublicintdescribeContents(){return0;}//把数据写入到parcel中@OverridepublicvoidwriteToParcel(Parcelparcel,inti){parcel.writeString(name);parcel.writeInt(age);}//我们还必须在person类中创建一个CREATOR常量,这里创建了一个Parcelable.Creator接口的实现//并且将泛型类型指定为person,接着重写里面的两个方法//createFromParcel这个方法中读取刚才存入的字段//newArraypublicstaticfinalParcelable.Creator
说说它的传递方式,传入时候和我们之前写的Serializable是一样的,就不在重复,只是在读取的时候,有一点需要我们注意一下,就是方法名改变了:
personzhangxu3=(person)getIntent().getParcelableExtra("person");
它们俩的区别:
serializable的方式比较简单,但由于会把整个对象进行序列化,因此效率会比Parcelable低一些,所以在通常情况下我们还是建议使用Parcelable方式!
日志控制
在iOS中我们经常有用到这个日志控制的问题,在安卓中也是,就是在debug阶段我们需要大量的日志,但是在release状态我们是不需要的,日志不仅仅会增加程序运行的成本,还会泄漏一些重要的信息,所以在编译release状态我们是需要控制日志打印的,在安卓中我们可以写这样的一个类来进行处理。
classLogUntil{publicstaticfinalintVERBOSE=1;publicstaticfinalintDEBUG=2;publicstaticfinalintINFO=3;publicstaticfinalintWARN=4;publicstaticfinalintERROR=5;publicstaticfinalintNOTHING=6;publicstaticfinalintleven=VERBOSE;publicstaticvoidv(Stringtag,Stringmsg){if(leven<=VERBOSE){Log.d(tag,msg);}}publicstaticvoidd(Stringtag,Stringmsg){if(leven<=DEBUG){Log.d(tag,msg);}}publicstaticvoidi(Stringtag,Stringmsg){if(leven<=INFO){Log.d(tag,msg);}}publicstaticvoidw(Stringtag,Stringmsg){if(leven<=WARN){Log.d(tag,msg);}}publicstaticvoide(Stringtag,Stringmsg){if(leven<=ERROR){Log.d(tag,msg);}}}
上面的这段代码就是我们常用的日志控制,在我们要发布的时候,我们设置leven的值为NOTHING的时候我们的日志也就不见了!和我们iOS的理解方式是一样的,我们iOS中会用到DEBUG这个变量,具体的我也就不再多说了,有兴趣的可以自己找找这方面的问题,我们直说安卓的。
创建定时任务
下面我们用代码写一个Alarm的实际例子:
聊聊Doze模式
接下来看看在Doze模式下那些功能会受到影响:
1、网络访问被限制
2、系统忽略唤醒CPU或者屏幕操作
3、系统不再执行WIFI扫描
4、系统不再执行同步服务
5、Alarm任务将会在下次退出Doze模式的时候执行
多窗口
Android在7.0之后导入了多窗口模式,在这里我们可以大概的学习一下多窗口模式。
在这里我们说一下,在多窗口模式下并不会改变活动原有的生命周期,只是会将用户最近交互过的那个活动设置为运行状态,而将多窗口模式下另外一个可见的活动设置为暂停状态,如果这时候用户又和暂停的活动进行交互,那么该活动就会进入运行状态,之前处于运行状态的活动变成暂停状态。
前面我们说到在多窗口模式下,活动的生命周期是不会发生改变的,那么有一些问题我们就可以随之考虑一下:
比如说,在多窗口模式下,用户任然处于可以看到暂停状态的应用,那么像视频播放之类的应用在此时就应该是继续播放视频才对,因此,我们最好不要在活动的onPause方法中处理视频播放器的暂停逻辑,而是应该在onStop()方法中处理,并且在onStart方法中回复视频的播放。
另外,针对进入多窗口模式时候,活动会被重新创建,如果你想改变这一默认行为,可以在Androidmainfest.xml中进行如下配置:
禁止多窗口模式
Androidmainfest.xml中这样配置:
android:resizeableActivity="false"true表示支持,false表示禁止
这样就OK了吗?其实还有一个问题需要我们考虑一下这个问题,这个属性是在我们指定targetSdkVersion大于等于24的时候才有效的,那小于24呢?没有这个属性我们怎么处理呢?我们再这里说一种解决方案:
Android规定,如果项目指定的targetSdkVersion低于24,并且活动是不允许横竖屏切换的,那么该应用也将不支持多窗口模式。
默认情况下,我们的应用是支持横竖屏切换的,如果想想要让应用不允许横竖屏切换,那么就需要在Androidmainfest.xml的