29.1 全局获取Context的技巧
class MyApplication: Application() {
companion object {
@SuppressLint("StaticFieldLeak")
lateinit var context: Context
}
override fun onCreate() {
super.onCreate()
context = applicationContext
}
}
AndroidManifest.xml中配置程序启动的时候应该初始化MyApplication类
<application
android:name=".MyApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
/application>
29.2 使用Intent传递对象
1. Serializable方式
只需要让一个类去实现Serializable这个接口就可以了
class Person : Serializable {
var name = ""
var age = 0
}
// 调用
val person = Person()
person.name = "Tom"
person.age = 20
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("person_data", person)
startActivity(intent)
// 获取
val person = intent.getSerializableExtra("person_data") as Person
需要注意:传递过去的对象已经是一个新的对象了。
2 Parcelable方式
Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样就能实现传递对象的功能了。
class Person : Parcelable {
var name = ""
var age = 0
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(name) // 写出name
parcel.writeInt(age) // 写出age
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<Person> {
override fun createFromParcel(parcel: Parcel): Person {
val person = Person()
person.name = parcel.readString() ?: "" // 读取name
person.age = parcel.readInt() // 读取age
return person
}
override fun newArray(size: Int): Array<Person?> {
return arrayOfNulls(size)
}
}
}
使用
// 传递
intent.putExtra("person_data", person)
// 获取
val person = intent.getParcelableExtra("person_data") as Person
不过,这种实现方式写起来确实比较复杂,为此Kotlin给我们提供了另外一种更加简便的用法,但前提是要传递的所有数据都必须封装在对象的主构造函数中才行。
@Parcelize
class Person(var name: String, var age: Int) : Parcelable
29.3 定制自己的日志工具
object LogUtil {
private const val VERBOSE = 1
private const val DEBUG = 2
private const val INFO = 3
private const val WARN = 4
private const val ERROR = 5
private var level = VERBOSE
fun v(tag: String, msg: String) {
if (level <= VERBOSE) {
Log.v(tag, msg)
}
}
fun d(tag: String, msg: String) {
if (level <= DEBUG) {
Log.d(tag, msg)
}
}
fun i(tag: String, msg: String) {
if (level <= INFO) {
Log.i(tag, msg)
}
}
fun w(tag: String, msg: String) {
if (level <= WARN) {
Log.w(tag, msg)
}
}
fun e(tag: String, msg: String) {
if (level <= ERROR) {
Log.e(tag, msg)
}
}
}
我们只需要通过修改level变量的值,就可以自由地控制日志的打印行为。比如让level等于VERBOSE就可以把所有的日志都打印出来,让level等于ERROR就可以只打印程序的错误日志。
29.4 调试
调试Android程序和IOS类似
添加断点:代码行的左侧点击一下
取消断点:再次点击断点一下
进入调试模式:工具栏运行按钮右边Debug app按钮,或者Attach Debugger to Android Process。
29.5 深色主题
在res下有2个文件夹
- values: 浅色模式
- values-night: 深色模式
里面有colors.xml、themes.xml可配置
// 浅色模式 values/colors.xml中
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="textColor">#FF333333</color>
<color name="textBackColor">#FFEEEEEE</color>
</resources>
// 深色模式v values-night/colors.xml中
<resources>
<color name="textColor">#FFEEEEEE</color>
<color name="textBackColor">#FF333333</color>
</resources>
使用
<TextView
android:id="@+id/textView"
android:text="Hello World!"
android:textSize="20sp"
android:textColor="@color/textColor"
android:background="@color/textBackColor"
/>
判断是否是深色模式
fun isDarkTheme(context: Context): Boolean {
val flag = context.resources.configuration.uiMode and
Configuration.UI_MODE_NIGHT_MASK
return flag == Configuration.UI_MODE_NIGHT_YES
}