Android高阶技巧

1、管理全局状态信息

还需要告知系统,当程序启动的时候应该初始化MyApplication类,而不是默认的Application类。这一步也很简单,在AndroidManifest.xml文件的标签下进行指定就可以了。

<application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.JetpackApp"
        tools:targetApi="31">

这样我们就实现了一种全局获取Context的机制,之后不管你想在项目的任何地方使用Context,只需要调用一下MyApplication.context就可以了。

例如,简化Toast

package com.jpc.jetpackapp

import android.widget.Toast

object ToastUtil {
    fun String.showToast(duration: Int = Toast.LENGTH_SHORT){
        Toast.makeText(MyApplication.context, this, duration).show()
    }
    fun Int.showToast(duration: Int = Toast.LENGTH_SHORT){
        Toast.makeText(MyApplication.context, this, duration).show()
    }
}

// 调用
"hello".showToast()
2、使用Intent传递对象
(1)方式一 Serializable

Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。至于序列化的方法非常简单,只需要让一个类去实现Serializable这个接口就可以了。
定义对象

package com.jpc.jetpackapp

import java.io.Serializable

class Person: Serializable {
// 需要默认值
    var name: String = ""
    var age: Int = 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所支持的数据类型,这样就能实现传递对象的功能了。

package com.jpc.jetpackapp

import android.os.Parcel
import android.os.Parcelable

class Student: Parcelable {
    var name = ""
    var age = 0

    override fun writeToParcel(dest: Parcel, flags: Int) {
        dest.writeString(name) // 写出Name
        dest.writeInt(age)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR: Parcelable.Creator<Student>{
        override fun createFromParcel(source: Parcel?): Student {
            val student = Student()
            // 里读取的顺序一定要和刚才写出的顺序完全相同
            student.name = source?.readString() ?: "" // 读取Name
            student.age = source?.readInt() ?: 0
            return student
        }

        override fun newArray(size: Int): Array<Student?> {
            return arrayOfNulls(size)
        }
    }
}
val person = intent.getParcelableExtra("person_data") as Person

Kotlin给我们提供了另外一种更加简便的用法,但前提是要传递的所有数据都必须封装在对象的主构造函数中才行。

@Parcelize
class Person(var name: String, var age: Int) : Parcelable

Serializable的方式较为简单,但由于会把整个对象进行序列化,因此效率会比Parcelable方式低一些,所以在通常情况下,还是更加推荐使用Parcelable的方式来实现Intent传递对象的功能。

3、定制日志工具
package com.jpc.jetpackapp

import android.util.Log

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)
        }
    }
}

这样就把一个自定义的日志工具创建好了,之后在项目里,我们可以像使用普通的日志工具一样使用LogUtil。比如打印一行DEBUG级别的日志可以这样写。

LogUtil.d("TAG", "debug log")

我们只需要通过修改level变量的值,就可以自由地控制日志的打印行为。比如让level等于VERBOSE就可以把所有的日志都打印出来,让level等于ERROR就可以只打印程序的错误日志。
使用了这种方法之后,刚才所说的那个问题也就不复存在了,你只需要在开发阶段将level指定成VERBOSE,当项目正式上线的时候将level指定成ERROR就可以了。

4、使用视图绑定
android {
    ...
    buildFeatures {
        viewBinding = true
    }
}

如果某个xml布局不使用

<LinearLayout
        ...
        tools:viewBindingIgnore="true" >
    ...
</LinearLayout>
private lateinit var binding: ResultProfileBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ResultProfileBinding.inflate(layoutInflater)
    val view = binding.root
    setContentView(view)
}
binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }
  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JPC客栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值