二十九、Android-进阶

76 阅读1分钟

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
    }