您的位置:首页 > 移动开发 > Android开发

android MVVM框架学习总结(一)

2018-03-31 15:12 393 查看
android MVVM框架学习总结
1.简单的数据绑定示例

2.事件处理

3. Layout细节

android MVVM框架学习总结

1.简单的数据绑定示例

(1)布局文件这样写

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}"/>
</LinearLayout>
</layout>


在标签中 描述了一个变量user,它对应的类型为”com.example.User”

布局中使用“@ { }”语法来书写表达式。如为TextView的文本设置成user. firstName.

(2) 数据对象这样写

public class User {
public final String firstName;
public final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}


在数据绑定中,访问@{user.firstName},那么默认就会访问同名的属性firstName,或对应的getFirstName方法。

(3)数据绑定

默认情况下,绑定类将基于布局文件的名称来产生

如布局文件为main_activity.xml,这样生成的类是 MainActivityBinding

如下设置Activity的contentView:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
User user = new User("Test", "User");
binding.setUser(user);
}


上文说,在xml中用表达式可以获取数据,那么同样的,在代码中也可以设置数据,如这里的:binding.setUser(user);

还可以使用inflate的方式来获取生成数据绑定类:

MainActivityBinding binding = MainActivityBinding.inflate(getLayoutInflater());


如果是在一个adapter中来使用,那么可以如下:

ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
//or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);


2.事件处理

可以在xml中编写表达式处理事件。比如 View.OnLongClickListener有一个方法为onLongClick(),那么它对应的事件就是android:onLongClick。当绑定事件后,会自动将该listener绑定在View上。处理事件有两种方法,

1. 方法引用:可以引用符合listener 任意方法签名规则的方法。

2. 监听器绑定:使用lambda表达式。

1.方法引用

比如定义一个符合OnClickListener#onClick(View view)方法参数签名规则的方法:

public class MyHandlers {
public void onClickFriend(View view) { ... }
}


如下在xml中绑定并使用:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="handlers" type="com.example.Handlers"/>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"
android:onClick="@{handlers::onClickFriend}"/>
</LinearLayout>
</layout>


2.监听器绑定

表达式使用的方法就可以定义的比较随意了,不用像”方法引用”那样遵循特定规则,如一个方法

public class Presenter {
public void onSaveClick(Task task){}
}


xml中使用它

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="task" type="com.android.example.Task" />
<variable name="presenter" type="com.android.example.Presenter" />
</data>
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
<Button android:layout_width="wrap_content" android:layout_height="wrap_content"
android:onClick="@{() -> presenter.onSaveClick(task)}" />
</LinearLayout>
</layout>


像上面,我们并没有定义onClick(android.view.View) 参数view。监听器绑定,允许我们忽略所有的参数。如果想要使用参数,可以忽略参数类型,随意定义一个名字。监听器绑定还有很多灵活的写法,可以参考官方文档。

3. Layout细节

(1) import

1) 在标签中,import 一些class,就像在java 代码中一样

如:
<import type="android.view.View"/>


2) 当类名过长或者有类名称冲突,其中一个类可以重命名一个别名

<import type="com.grandstream.gsmarket.R.string" alias="Strings"/>

<import type="android.view.View"/>
<import type="com.example.real.estate.View"
alias="EsView"/>


3) 也可以在表达式中运用静态属性或方法,使用MyStringUtils.capitalize():

<data>
<import type="com.example.MyStringUtils"/>
<variable name="user" type="com.example.User"/>
</data>
…
<TextView
android:text="@{MyStringUtils.capitalize(user.lastName)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>


示例代码

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

<variable
name="viewmodel"
type="com.grandstream.gsmarket.appdetail.AppDetailItemViewModel" />

<import type="android.view.View"/>

<import type="com.grandstream.gsmarket.R.string" alias="Strings"/>
</data>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/download_count_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:singleLine="true"
android:textColor="#999999"
android:textSize="36px"
android:text='@{viewmodel.getContext().getString(Strings.download) + viewmodel.downloadCount}'/>
</LinearLayout>


(2)可以定义多个标签

这些variable变量在编译时会进行类型检查,如果一个variable实现了Observable接口或是一个Observable的collection,那就需要在type中声明;如果不是一个Observable的实现,那么该variable就不会被观察到.

<data>

<import type="android.view.View" />

<variable
name="view"
type="com.grandstream.gsmarket.apps.ApkListFragment" />

<variable
name="viewmodel"
type="com.grandstream.gsmarket.apps.AppsViewModel" />

</data>


(3)自定义绑定 class names

默认情况下,基于布局文件的名称而生成绑定类,开头大写,然后移除下划线,再加上后缀”Binding”。这个类将被放置在一个数据绑定包中,该包位于moudle包下。例如, 布局文件contact_item.xml将生成ContactItemBinding。如果moudle的包名为com.example.my.app, 那么它将被放置在com.example.my.app.databinding下,通过调整data元素的class属性,绑定类可以重命名或放置在不同的包。

<data class="ContactItem">
...
</data>


这会生成在moudle下的databinding包下,如果要生成moudle包下,可以使用”.”前缀:

<data class=".ContactItem">
...
</data>


在下面这种情况下,ContactItem直接生成在模块包下。可以使用任何完整的包路径:

<data class="com.example.ContactItem">
...
</data>


(4)include

variables可以传递给使用了include标签的子布局中,如

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/name"
bind:user="@{user}"/>
<include layout="@layout/contact"
bind:user="@{user}"/>
</LinearLayout>
</layout>


如上,在name.xml和contract.xml中都可以使用变量user了

不支持在merge下直接使用include的情形。

(5)表达式语言

1)共同的特征

表达式语言看起来很像Java表达式。如下这些都是相同的:

Mathematical + - / * %
String concatenation +
Logical && ||
Binary & | ^
Unary + - ! ~
Shift >> >>> <<
Comparison == > < >= <=
instanceof
Grouping ()
Literals - character, String, numeric, null
Cast
Method calls
Field access
Array access []
Ternary operator ?:


例:

android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'


2)不支持的操作符

this、new、super 如这些,还是只能在java类中使用


3)合并null操作符

如下使用 “??” 操作符

android:text="@{user.displayName ?? user.lastName}"


等价于

android:text="@{user.displayName != null ? user.displayName : user.lastName}"


4)属性引用

如下,user有getLastName(),可以简单引用:

android:text="@{user.lastName}"


5)NullPointerException处理

数据绑定代码会自动检查null值,避免NullPointerException。例如String类型默认为null, Int类型默认0.

6)集合

一般的集合都可以使用”[]”操作符: arrays, lists, sparse lists, and maps。例

<data>
<import type="android.util.SparseArray"/>
<import type="java.util.Map"/>
<import type="java.util.List"/>
<variable name="list" type="List<String>"/>
<variable name="sparse" type="SparseArray<String>"/>
<variable name="map" type="Map<String, String>"/>
<variable name="index" type="int"/>
<variable name="key" type="String"/>
</data>
…
android:text="@{list[index]}"
…
android:text="@{sparse[index]}"
…
android:text="@{map[key]}"


7)字符串引用

如下,可以使用单引号在属性值上,用双引号在字符串字面值上:

android:text='@{map["firstName"]}'


也可以反过来

android:text="@{map[`firstName`}"
android:text="@{map['firstName']}"


8)资源

可以使用正常的访问资源的表达式语法:

android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"


可以为格式字符串和复数提供参数:

android:text="@{@string/nameFormat(firstName, lastName)}"
android:text="@{@plurals/banana(bananaCount)}"


一些资源需要显示的引用

TypeNormal ReferenceExpression Reference
String[]@array@stringArray
int[]@array@intArray
TypedArray@array@typedArray
Animator@animator@animator
StateListAnimator@animator@stateListAnimator
color int@color@color
ColorStateList@color@colorStateList
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: