美文网首页
Databinding-samples(三)-Observabl

Databinding-samples(三)-Observabl

作者: 烧伤的火柴 | 来源:发表于2020-04-28 14:32 被阅读0次

介绍

本篇文章介绍ObservableFieldActivity中的知识点

observable_field_profile.xml 布局文件

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
    <data>

        <import type="com.example.android.databinding.basicsample.R"/>
        <import type="com.example.android.databinding.basicsample.util.ConverterUtil"/>
        <variable
            name="user"
            type="com.example.android.databinding.basicsample.data.ObservableFieldProfile" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/name"
            ...
            android:text="@{user.name}"
            android:textAppearance="@style/TextAppearance.AppCompat.Large"
            .../>

        <TextView
            android:id="@+id/lastname"
           ...
            android:text="@{user.lastName}"/>

        <!-- Layout expressions can be *too* powerful. It's preferred to avoid this type of
        view logic in the layout. Instead, use Binding Adapters (see ViewModelActivity).

        Also, `app:srcCompat` is bound to setImageResource.
        -->
        <ImageView
            android:id="@+id/imageView"
            ...
            android:tint="@{user.likes &gt; 9 ? @color/star : @android:color/black}"
            app:srcCompat="@{user.likes &lt; 4 ? R.drawable.ic_person_black_96dp : R.drawable.ic_whatshot_black_96dp }"/>

        <TextView
            android:id="@+id/likes"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{Integer.toString(user.likes)}"
            .../>

        <Button
            android:id="@+id/like_button"
            android:onClick="onLike"
            android:text="@string/like"
            .../>

        <TextView
            android:id="@+id/name_label"
             .../>

        <TextView
            android:id="@+id/lastname_label"
            .../>

        <TextView
            android:id="@+id/likes_label"
            .../>

        <!-- android:progressTint is only available in API 21+ so we deal with that in the
        Binding Adapter.

        The android:visibility attribute is used to showcase BindingConversions,
        see the README for a better alternative with a BindingAdapter.-->
        <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:max="@{100}"
            android:visibility="@{ConverterUtil.isZero(user.likes)}"
            app:progressScaled="@{user.likes}"
            .../>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

1.布局文件中导入了两个类R和ConverterUtil,定义了一个变量user,user的类型是ObservableFieldProfile
name的TextView很简单的使用表达式引用user的name属性,设置给android:text,即android:text="@{user.name}"
lastname和name一样。

2.imageView的ImageView中android:tint 使用三目运算符表达式,返回tint需要的值:android:tint="@{user.likes > 9 ? @color/star : @android:color/black}"

3.app:srcCompat属性本来接收的是int类型:@drawable/xxx,但是这里传递的是R.drawable.XXX,传递的值和属性本来接收参数不一致,这时就需要使用BindingMethods自定义方法,将setImageResource和app:srcCompat属性绑定到一起。

@BindingMethods(
        BindingMethod(type = ImageView::class,
                attribute = "app:srcCompat",
                method = "setImageResource"))
class MyBindingMethods

4.likes中 android:text接收Integer.toString(user.likes)方法,因为系统会默认import java.lang.*的类,所以Integer和String不需要导入了

5.progressBar中的android:visibility 接收到是ConverterUtil 的静态方法isZero

object ConverterUtil {
    @JvmStatic fun isZero(number: Int): Boolean {
        return number == 0
    }
}

kotlin中的静态方法在java中使用需要添加JvmStatic注解
这个方法返回的是boolean类型,但是android:visibility 接收的是一个VISIBLE, GONE and INVISIBLE 中的一个值,所以我们需要进行类型转换:

object BindingConverters{

    @BindingConversion
    @JvmStatic fun booleanToVisibility(isNotVisible: Boolean): Int {
        return if (isNotVisible) View.GONE else View.VISIBLE
    }
}

6.app:progressScaled是自定义属性,这里的自定义方式是通过BindAdapter

    @BindingAdapter(value = ["app:progressScaled", "android:max"], requireAll = true)
    @JvmStatic fun setProgress(progressBar: ProgressBar, likes: Int, max: Int) {
        progressBar.progress = (likes * max / 5).coerceAtMost(max)
    }

coerceAtMost最大值是max(100) 所以progressBar根据likes1-5增加。
requireAll = true表示value数组中的属性要一起使用,任何一个属性发生变化都会调用这个方法。

Data类

data class ObservableFieldProfile(
        val name: String,
        val lastName: String,
        val likes: ObservableInt
)

其中likes是ObservableInt类型,即可观察类型,当likes的值变化的时候,布局中引用likes的视图都会自动更新

Activity文件

class ObservableFieldActivity : AppCompatActivity() {

    private val observableFieldProfile = ObservableFieldProfile("Ada", "Lovelace", ObservableInt(0))

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding: ObservableFieldProfileBinding =
                DataBindingUtil.setContentView(this, R.layout.observable_field_profile)
        binding.user = observableFieldProfile
    }

    /**
     * This method is triggered by the `android:onclick` attribute in the layout. It puts business
     * logic in the activity, which is not ideal. See {@link ViewModelActivity} for a better
     * solution.
     */
    fun onLike(view: View) {
        observableFieldProfile.likes.set(observableFieldProfile.likes.get() + 1)
    }
}

onCreate通过binding.user = observableFieldProfile,将observableFieldProfile实例赋值给xml中的user属性。
其中onLike的注解很重要:
这种方式会把复杂的逻辑放到了Activity中,Activity本质是不处理业务的。

总结

这个页面主要展示了databinding的很多使用方式,而且这种设计模式就是我们熟悉的mvc模式,mvc的缺点,耦合性强,不易测试,不易扩展,在这里都体现了。

相关文章

网友评论

      本文标题:Databinding-samples(三)-Observabl

      本文链接:https://www.haomeiwen.com/subject/wmxvwhtx.html