1.Intent以Parcelable方式传递对象
我在项目中传递类对象,一般用的是Serializable方式,这种方式简单易掌握,但是用Parcelable也可以传递类对象,只不过Serializable是将对象序列化,而Parcelable的方式的实现原理是将一个完整的对象进行分解来实现传递对象的功能。
public class Person implements Parcelable {
private String name;
private int age;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>(){
@Override
public Person createFromParcel(Parcel source) {
Person person = new Person();
person.name = source.readString();//读取的顺序要与写进去的顺序一致
person.age = source.readInt();
return person;
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
}
Serializable的效率比Parceable效率要低一些,所以在通常情况下还会更加推荐使用Parceable的方式来实现Intent传递对象的功能。2.多窗口模式编程
Android7.0引入了一个很有特色的功能——多窗口模式,允许我们在同一个屏幕中同时打开两个应用程序,那么怎么进入多窗口模式呢?
(1)在Overview列表界面长按任意一个活动的标题,将该活动拖动到屏幕突出显示的区域,就可以进入多窗口模式。
(2)打开任意一个程序,长按Overview按钮,也可以进入多窗口模式。
横屏则是左右分开,竖屏则是上下分开。
如果想要退出多窗口模式,只需要再次长按Overview按钮,或者将屏幕中央的分割线向屏幕任意一个方向拖动到底即可。注意开发时要考虑到适配。
至于生命周期,多窗口模式不会改变活动原有的生命周期,只是会将用户最近交互过的那个活动设置为运行状态,而多窗口模式下的另外一个可见的活动设置为暂停状态,如果这时用户又去和暂停的活动进行交互,那么该活动就会变成运行状态,之前处于运行状态的活动就会变成暂停状态。
进入多窗口模式后,Activity会重新创建,除此之外,像横竖屏操作也会使得活动重新创建。
onPause->onStop->onDestory->onCreate->onStart->onResume->onPause
这个活动就会处于暂停状态,点击另一个活动就会执行OnCreate->onStart->onResume。但你与第一个活动交互的时候,这个就会进入onPause状态,而你政治交互的则会从onPause()->onresume().
另外,针对进入多窗口模式活动会被重新创建,如果你想改变这一默认行为,可以在AndroidManifest.xml中对活动进行如下配置:
android:configChanges="orientation|keyboardHidden|screenLayout|screenSize"
加入这行配置后,不管进入多窗口模式,还是横竖屏切换,活动都不会重新创建,而是会将屏幕发生变化的事件通知到Activity的onConfigurationChanged()方法当中,因此如果你想在屏幕发生变化的时候进行相应的逻辑处理,那么在活动中重新onConfigurationChanged()方法即可。
那么你肯定要问如何禁用多窗口模式?很简单
android:resizeableActivity="false"
但是这个属性用法虽然简单,但是它还存在一个问题,这个属性只有targetSdkVersion指定为24或者以上才能用,如果是23,我们依旧可以进入多窗口模式,那么还有一种解决方案。Android规定,如果项目指定的targetSdkVersion低于24,并且活动是不允许横竖屏切换的,那么该应用也将不支持多窗口模式的。
android:screenOrientation="portrait"
这样就可以了。
3. Lambda表达式
我们本地安装的JDK都是Java8的版本,Java8中有很多新特性,但是可以立即应用到项目的也只有Lambda表达式,它最低兼容到了Android2.3.
Lambda表达式本质上是一种匿名方法,它既没有方法名,也没有访问修饰符和返回值类型,使用它来编写代码将会更加简洁,易读。使用它我们需要在build.gradle中进行如下配置:
android{
...
defaultConfig{
jackOptions.enabled = true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
...
}
之后我们就可以来使用Lambda了。举个例子。我们传统情况下开启一个子线程的写法
new Thread(new Runnable(){
@Override
public void run() {
}
});
而使用Lambda表达式则可以这样写:
new Thread( ()-> {
}).start();
你可能会问为什么可以使用这么简洁的写法呢?那是因为Thread类的构造函数接收到的参数是一个Runnable接口,并且该接口中只有一个待实现的方法。注意,凡是这种只有一个待实现方法的接口,都可以使用Lambda表达式的写法,比如创建一个类类似于上述接口的匿名类实现需要这样写:
Runnable runnable = new Runnable() {
@Override
public void run() {
}
};
那么我们使用Lambda表达式就可以这么写:
Runnable runnable = ()->{
};
再比如我们需要自定义一个接口
public interface MyListener{
String doSomething(String a,int b);
}
我们使用Lambda表达式创建MyListener接口的匿名实现写法如下
MyListener listener = (String a,int b)->{
String result = a + b;
return result;
}
另外,Java可以根据上下文自动推断出Lambda表达式中的参数类型,因此上面的代码也可以简化成如下写法:
MyListener listener = (a,b)->{
String result = a +b;
return result;
}
Java会自动推断出参数a是String类型,参数b是int类型,从而使得我们的代码变的更加精简。
接下来再举个例子,比如现在有个方法需要接收MyListener参数的
public void hello(MyListener listener) {
String a = "hello Lambda"
int b = 1024;
String result = listener.doSomething(a,b);
}
那么我们在调用hello()这个方法的时候就可以这样写:
hello((a,b)->{
String result = a + b;
return result;
})
举了这么多例子,你应该已经把Lambda表达式的写法基本掌握了,其实只要是符合接口中只有一个待实现方法这个规则的功能,都是可以使用Lambda表达式来编写的,除了刚才举例说明的开启子线程外,还有像设置点击事件之类的功能也是非常适合使用Lambda表达式的
比如点击事件,传统的写法是这样的
parent.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
而我们使用Lambda表达式则可以简化成这个样子
parent.setOnClickListener(v->{
});
这样我们基本上把Lambda的只有内容掌握了,当然有些人可能并不喜欢Lambda表达式这种极简主义的写法,不过Java8对于哪一种写法都是完全支持的,至于如何选择全凭自己,多一种选择并不是坏事。