Skip to content

Commit a9eb0bd

Browse files
Change for 1.3.0
1 parent fa93c53 commit a9eb0bd

File tree

22 files changed

+693
-346
lines changed

22 files changed

+693
-346
lines changed

app/src/main/java/com/dylanc/viewbinding/sample/MainActivity.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ package com.dylanc.viewbinding.sample
1919
import android.os.Bundle
2020
import android.os.Handler
2121
import android.os.Looper
22+
import android.widget.Toast
2223
import androidx.appcompat.app.AppCompatActivity
2324
import androidx.recyclerview.widget.DiffUtil
24-
import com.dylanc.viewbinding.ListAdapter
25+
import com.dylanc.viewbinding.base.simpleListAdapter
2526
import com.dylanc.viewbinding.nonreflection.binding
2627
import com.dylanc.viewbinding.sample.databinding.ActivityMainBinding
2728
import com.dylanc.viewbinding.sample.databinding.ItemFooBinding
@@ -45,12 +46,18 @@ class MainActivity : AppCompatActivity() {
4546
}, 2000)
4647
}
4748
recyclerView.adapter = adapter
48-
adapter.submitList(list)
49+
}
50+
adapter.submitList(list)
51+
adapter.doOnItemClick { item, _ ->
52+
Toast.makeText(this, item.value, Toast.LENGTH_SHORT).show()
53+
}
54+
adapter.doOnItemLongClick { item, _ ->
55+
Toast.makeText(this, "long click ${item.value}", Toast.LENGTH_SHORT).show()
4956
}
5057
}
5158

52-
private val adapter = ListAdapter<Foo, ItemFooBinding>(DiffCallback()) {
53-
binding.tvFoo.text = it.value
59+
private val adapter = simpleListAdapter<Foo, ItemFooBinding>(DiffCallback()) { item ->
60+
tvFoo.text = item.value
5461
}
5562

5663
class DiffCallback : DiffUtil.ItemCallback<Foo>() {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.dylanc.viewbinding.sample.item
2+
3+
import android.view.LayoutInflater
4+
import android.view.ViewGroup
5+
import androidx.recyclerview.widget.DiffUtil
6+
import androidx.recyclerview.widget.ListAdapter
7+
import androidx.viewbinding.ViewBinding
8+
import com.dylanc.viewbinding.BindingViewHolder
9+
10+
inline fun <T, reified VB : ViewBinding> listAdapter(
11+
diffCallback: DiffUtil.ItemCallback<T>,
12+
crossinline onBindViewHolder: BindingViewHolder<VB>.(T) -> Unit
13+
) = object : ListAdapter<T, BindingViewHolder<VB>>(diffCallback) {
14+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
15+
BindingViewHolder<VB>(parent)
16+
17+
override fun onBindViewHolder(holder: BindingViewHolder<VB>, position: Int) {
18+
onBindViewHolder(holder, currentList[position])
19+
}
20+
}
21+
22+
inline fun <T, reified VB : ViewBinding> listAdapter(
23+
diffCallback: DiffUtil.ItemCallback<T>,
24+
noinline inflate: (LayoutInflater, ViewGroup, Boolean) -> VB,
25+
crossinline onBindViewHolder: com.dylanc.viewbinding.nonreflection.BindingViewHolder<VB>.(T) -> Unit
26+
) = object : ListAdapter<T, com.dylanc.viewbinding.nonreflection.BindingViewHolder<VB>>(diffCallback) {
27+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
28+
com.dylanc.viewbinding.nonreflection.BindingViewHolder(parent, inflate)
29+
30+
override fun onBindViewHolder(holder: com.dylanc.viewbinding.nonreflection.BindingViewHolder<VB>, position: Int) {
31+
onBindViewHolder(holder, currentList[position])
32+
}
33+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2020. Dylan Cai
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
@file:Suppress("unused")
18+
19+
package com.dylanc.viewbinding.base
20+
21+
import android.view.ViewGroup
22+
import androidx.recyclerview.widget.DiffUtil
23+
import androidx.recyclerview.widget.ListAdapter
24+
import androidx.recyclerview.widget.RecyclerView
25+
import androidx.viewbinding.ViewBinding
26+
27+
inline fun <T, VB : ViewBinding> simpleListAdapter(
28+
diffCallback: DiffUtil.ItemCallback<T>,
29+
crossinline onBindViewHolder: VB.(T) -> Unit
30+
) = object : SimpleListAdapter<T, VB>(diffCallback) {
31+
32+
override fun onBindViewHolder(binding: VB, item: T, position: Int) {
33+
onBindViewHolder(binding, item)
34+
}
35+
}
36+
37+
abstract class SimpleListAdapter<T, VB : ViewBinding>(
38+
diffCallback: DiffUtil.ItemCallback<T>
39+
) : ListAdapter<T, SimpleListAdapter.BindingViewHolder<VB>>(diffCallback) {
40+
41+
private var onItemClickListener: ((T, Int) -> Unit)? = null
42+
private var onItemLongClickListener: ((T, Int) -> Unit)? = null
43+
44+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingViewHolder<VB> =
45+
BindingViewHolder(inflateBindingWithGeneric<VB>(parent)).apply {
46+
itemView.setOnClickListener {
47+
onItemClickListener?.invoke(getItem(adapterPosition), adapterPosition)
48+
}
49+
itemView.setOnLongClickListener {
50+
onItemLongClickListener?.invoke(getItem(adapterPosition), adapterPosition)
51+
onItemLongClickListener != null
52+
}
53+
}
54+
55+
override fun onBindViewHolder(holder: BindingViewHolder<VB>, position: Int) {
56+
onBindViewHolder(holder.binding, getItem(position), position)
57+
}
58+
59+
fun doOnItemClick(block: (T, Int) -> Unit) {
60+
onItemClickListener = block
61+
}
62+
63+
fun doOnItemLongClick(block: (T, Int) -> Unit) {
64+
onItemLongClickListener = block
65+
}
66+
67+
abstract fun onBindViewHolder(binding: VB, item: T, position: Int)
68+
69+
class BindingViewHolder<VB : ViewBinding>(val binding: VB) : RecyclerView.ViewHolder(binding.root)
70+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (c) 2020. Dylan Cai
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
@file:Suppress("unused")
18+
19+
package com.dylanc.viewbinding
20+
21+
import androidx.activity.ComponentActivity
22+
import androidx.databinding.ViewDataBinding
23+
import androidx.viewbinding.ViewBinding
24+
25+
inline fun <reified VB : ViewBinding> ComponentActivity.binding() = lazy {
26+
inflateBinding<VB>(layoutInflater).also { binding ->
27+
setContentView(binding.root)
28+
if (binding is ViewDataBinding) binding.lifecycleOwner = this
29+
}
30+
}

viewbinding-ktx/src/main/java/com/dylanc/viewbinding/BindingViewHolder.kt

Lines changed: 0 additions & 68 deletions
This file was deleted.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (c) 2020. Dylan Cai
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
@file:Suppress("unused")
18+
19+
package com.dylanc.viewbinding
20+
21+
import android.app.Dialog
22+
import androidx.viewbinding.ViewBinding
23+
24+
inline fun <reified VB : ViewBinding> Dialog.binding() = lazy {
25+
inflateBinding<VB>(layoutInflater).also { setContentView(it.root) }
26+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (c) 2020. Dylan Cai
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
@file:Suppress("unused")
18+
19+
package com.dylanc.viewbinding
20+
21+
import android.view.LayoutInflater
22+
import androidx.databinding.ViewDataBinding
23+
import androidx.fragment.app.Fragment
24+
import androidx.lifecycle.DefaultLifecycleObserver
25+
import androidx.lifecycle.LifecycleOwner
26+
import androidx.viewbinding.ViewBinding
27+
import kotlin.properties.ReadOnlyProperty
28+
import kotlin.reflect.KProperty
29+
30+
inline fun <reified VB : ViewBinding> Fragment.binding() =
31+
FragmentBindingProperty(VB::class.java)
32+
33+
inline fun <reified VB : ViewBinding> Fragment.binding(method: Method) =
34+
if (method == Method.BIND) FragmentBindingProperty(VB::class.java) else FragmentInflateBindingProperty(VB::class.java)
35+
36+
class FragmentBindingProperty<VB : ViewBinding>(private val clazz: Class<VB>) : ReadOnlyProperty<Fragment, VB> {
37+
38+
override fun getValue(thisRef: Fragment, property: KProperty<*>): VB =
39+
try {
40+
thisRef.requireView().getBinding(clazz, thisRef.viewLifecycleOwner)
41+
} catch (e: IllegalStateException) {
42+
throw IllegalStateException("The binding property has been destroyed.")
43+
}
44+
}
45+
46+
class FragmentInflateBindingProperty<VB : ViewBinding>(private val clazz: Class<VB>) : ReadOnlyProperty<Fragment, VB> {
47+
private var binding: VB? = null
48+
49+
@Suppress("UNCHECKED_CAST")
50+
override fun getValue(thisRef: Fragment, property: KProperty<*>): VB {
51+
if (binding == null) {
52+
try {
53+
binding = (clazz.getMethod("inflate", LayoutInflater::class.java).invoke(null, thisRef.layoutInflater) as VB)
54+
.also { binding -> if (binding is ViewDataBinding) binding.lifecycleOwner = thisRef.viewLifecycleOwner }
55+
} catch (e: IllegalStateException) {
56+
throw IllegalStateException("The binding property has been destroyed.")
57+
}
58+
thisRef.viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
59+
override fun onDestroy(owner: LifecycleOwner) {
60+
if (thisRef is BindingLifecycleOwner) thisRef.onDestroyViewBinding(binding!!)
61+
binding = null
62+
}
63+
})
64+
}
65+
return binding!!
66+
}
67+
}
68+
69+
enum class Method { BIND, INFLATE }
70+
71+
interface BindingLifecycleOwner {
72+
fun onDestroyViewBinding(destroyingBinding: ViewBinding)
73+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2020. Dylan Cai
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
@file:Suppress("unused")
18+
19+
package com.dylanc.viewbinding
20+
21+
import androidx.viewbinding.ViewBinding
22+
import com.google.android.material.navigation.NavigationView
23+
24+
inline fun <reified VB : ViewBinding> NavigationView.setHeaderView(index: Int = 0, block: VB.() -> Unit) =
25+
getHeaderView(index)?.getBinding<VB>()?.run(block)

0 commit comments

Comments
 (0)