Android开发高级技巧
全局获取context
前提:或许目前你还没有为得不到Context而发愁过,因为我们很多的操作是在Activity中进行的,而Activity本身就是一个Context对象。但是,当应用程序的架构逐渐开始复杂起来的时候,很多逻辑代码将脱离Activity类,但此时你又恰恰需要使用Context,也许这个时候你就会感到有些伤脑筋了。
解决:Android提供了一个Application类,每当应用程序启动的时候,系统就会自动将这个类进行初始化。而我们可以定制一个自己的Application类,以便于管理程序内一些全局的状态信息,比如全局Context。
1 | class MyApplication : Application() { |
这样我们就可以以静态变量的形式获取Context对象了。需要注意的是,将Context设置成静态变量很容易会产生内存泄漏的问题,所以这是一种有风险的做法.
但是由于这里获取的不是Activity或Service中的Context,而是Application中的Context,它全局只会存在一份实例,并且在整个应用程序的生命周期内都不会回收,因此是不存在内存泄漏风险的。
程序启动的时候应该初始化MyApplication类,在AndroidManifest.xml文件的<application>
标签下进行指定android:name=".MyApplication"
.
使用Intent传递对象
我们用的一直都是一些基础的数据类型如Int,String之类的。而不能传递我们自定义的对象。因此我们需要使用到序列化
Serializable方式
让你的类实现Serializable接口,把对象放入intent时,就是普通的方法intent.putExtra("person_data", person)
但是取出时需要使用特定的获取方法val person = intent.getSerializableExtra("person_data") as Person
,这样子才能获得序列化后的对象。注意,虽然你传递的对象内的值都一摸一样,但是这两个对象不是同一个对象。
Parcelable方式
1 | class Person : Parcelable { |
这种方式更加复杂,他需要实现Parcelable接口,然后重写他的describeContents()和writeToParcel()这两个方法。其中describeContents()方法直接返回0就可以了。而对于writeToParcel需要对他的每个属性使用write***
方法,如上所示。
除此之外我们还必须在Person类中提供一个名为CREATOR的匿名类实现。接着需要重写createFromParcel()和newArray()这两个方法,在createFromParcel()方法中,我们要创建一个Person对象进行返回,并读取刚才写出的name和age字段。其中name和age都是调用Parcel的readXxx()方法读取到的,注意这里读取的顺序一定要和刚才写出的顺序完全相同。而newArray()方法中的实现就简单多了,只需要调用arrayOfNulls()方法,并使用参数中传入的size作为数组大小,创建一个空的Person数组即可
然后传入intent还是一样的,但是取出时需要使用另外的方法val person =intent.getParcelableExtra("person_data") as Person
但是这种实现方法过于复杂,所以kotlin实现了简单的语法,只要加上@Parcelize注解即可。前提是所有数据必须封装在对象的主构造函数中,也就是简单的写为data class。
对比一下,Serializable的方式较为简单,但由于会把整个对象进行序列化,因此效率会比Parcelable方式低一些,所以在通常情况下,还是更加推荐使用Parcelable的方式来实现Intent传递对象的功能。