kotlin
的接口与java
的接口相比较而言有了一部分改动:
- 在
kotlin
中interface
不仅可以声明函数,还可以对函数进行实现.与类唯一不同的是它们是无状态的,所以属性需要子类去重写.类需要去负责保存接口属性的状态.
接口的作用:可以被用来从类中提取出相似行为的通用代码
例如:所有的Activity中基本都有ToolBar
,我们可以把所有Activity共享Toolbar
的代码存放在一个接口中.这样就会减少代码量,
在使用的时候把toolbar布局添加到不同activity的xml布局中,之后创建一个接口用来处理toolbar事件:
1. 设置title的内容和色值
2. 设置toolbar背景色
3. 指定是否显示上一步的导航动作
4. 滚动时的toolbar动画
5. 给所有的activity设置相同的菜单,甚至行为
……
然后让我们定义 ToolbarManager
interface ToolbarManager {
val toolbar: Toolbar //接口是无状态的,所以属性可以被定义,但是不能赋值。子类会实现这个接口并重写这个属性
// 另一方面,我们可以不使用重写来实现无状态的属性。也就是说属性不需要维护一个 backup field,而是手动处理(使用getter和setter)
var toolbarTitle: String
get() = toolbar.title.toString()
set(value) {
toolbar.title = value
}
fun initToolbar() {
// 加载toolbar的布局,并且添加点击事件,该处实际在项目中需要在activity中实现,因为不同activity中的点击事件和布局基本都是不相同的,
toolbar.inflateMenu(R.menu.menu_main)
toolbar.setOnMenuItemClickListener {
when (it.itemId) {
R.id.action_settings -> toolbar.ctx.startActivity<SettingsActivity>()
else -> App.instance.toast("Unknown option")
}
true
}
}
// 把函数作为参数传递到另一个函数中,并且作为参数的函数无返回值
fun enableHomeAsUp(up: () -> Unit) {
toolbar.navigationIcon = createUpDrawable()
toolbar.setNavigationOnClickListener { up() }
}
private fun createUpDrawable() = with(DrawerArrowDrawable(toolbar.ctx)) {
progress = 1f
this
}
// 用来设置view滑动时,toolbar消失和显示
fun attachToScroll(recyclerView: RecyclerView) {
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
// 使用了扩展函数
if (dy > 0) toolbar.slideExit() else toolbar.slideEnter()
}
})
}
......// 可以不断的在ToolbarManager中添加共享事件
}
使用:在使用的时候需要指定toolbar属性,我们可以使用 lazy 委托实现,这样会在我们第一次使用它的时候才会inflate
class MainActivity : AppCompatActivity(), ToolbarManager {
override val toolbar by lazy { find<Toolbar>(R.id.toolbar) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initToolbar()
// 将toolbar绑定到recyclerview上
attachToScroll(recyclerview)
}
private fun updateUI(weekForecast: ForecastList) {
// 将数据展示在UI布局中
toolbarTitle = "${weekForecast.city} (${weekForecast.country})"
}
}
…其他地方使用类似上面