android 数据绑定(1)Ativity、Fragment、Item绑定数据源
1.简介
官方文档:
https://developer.android.com/topic/libraries/data-binding
官方示例:
https://github.com/android/databinding-samples
作用:
把layout 与 数据对象关联,将layout上的组件与对象的成员绑定.让layout上的组件的值来自数据对象。如:
<TextView android:text="@{data.value}" />
2.简单用法:绑定Activity与数据源
2.1 打开绑定选项
只能在主module的 build.gradle 中打开,即使主module代码没有使用数据绑定,而他依赖的module使用了数据绑定,也要在主module中打开。
android {
...
dataBinding {
enabled = true
}
}
2.2 布局 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="data" type="com.example.databind.Data" /> <!--声明的对象data-->
<variable name="click" type="com.example.databind.Click" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout > <TextView android:text="@{data.value, default = value}" /> <!--值来自数据对象data-->
<Button android:onClick="@{() -> click.onStartClick(data)}" /> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
其中
- 跟元素<layout> 包含 元素 <data>和 跟布局<ConstraintLayout >
- <data>元素用来定义layout使用的数据源,可以使用稍微复杂语法,如<import ...>,见第4、5行。
- layout上的组件使用@{数据源名.成员}指定值,@{}内可以使用简单的的绑定表达式,如第10行。
2.3 数据对象 Data.java
package com.example.databind; public class Data {
public String key;
public int value; public Data(String key, int value){
this.key = key;
this.value = value;
} @Override
public String toString() {
return "key = " + key + " value = " + value;
}
}
2.4 建立绑定关系
package com.example.databind;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil; import com.example.databind.databinding.ActivityMainBinding; public class MainActivity extends AppCompatActivity { private ActivityMainBinding binding;
private Data data; private void init(){
data = new Data("time", );
binding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);
binding.setData(data);
binding.setClick(new Click(binding));
} @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
}
关于其中的 ActivityMainBinding :
- 第15行得到了把一个activity和一个布局关联,得到一个绑定对象 ActivityMainBinding,它是绑定框架生成的,见5。
- 写完layout后 Rebuild Project 一下 就可以生成它。
3. 绑定Fragment与数据源
3.1 布局文件
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data >
<variable name="data" type="com.example.databind.Data" />
<variable name="click" type="com.example.databind.Click" />
</data> <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Hello Data Binding !"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> <TextView
android:id="@+id/key"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@{data.key, default = key}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/value"
app:layout_constraintTop_toBottomOf="@+id/title"
app:layout_constraintHorizontal_chainStyle="packed"
/> <TextView
android:id="@+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:text="@{String.valueOf(data.value),default = value}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/key"
app:layout_constraintTop_toTopOf="@+id/key" /> <Button
android:id="@+id/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:onClick="@{() -> click.onStartClick(data)}"
android:text="start"
android:textAllCaps="false"
app:layout_constraintEnd_toStartOf="@+id/stop"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/key" /> <Button
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:onClick="@{() -> click.onStopClicked(data)}"
android:text="stop"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="@+id/start"
app:layout_constraintEnd_toStartOf="@+id/reset"
app:layout_constraintStart_toEndOf="@+id/start"
app:layout_constraintTop_toTopOf="@+id/start" /> <Button
android:id="@+id/reset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:text="reset"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="@+id/start"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/stop"
app:layout_constraintTop_toTopOf="@+id/start"
app:layout_constraintVertical_bias="1.0" /> <Button
android:id="@+id/list_fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="list fragment"
android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/stop" /> <EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintEnd_toEndOf="@+id/list_fragment"
app:layout_constraintStart_toStartOf="@+id/list_fragment"
app:layout_constraintTop_toBottomOf="@+id/list_fragment" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
3.2 数据类
Data.java
package com.example.databind; public class Data {
public String key;
public int value; public Data(String key, int value){
this.key = key;
this.value = value;
} @Override
public String toString() {
return "key = " + key + " value = " + value;
}
}
click.java
package com.example.databind;
import android.util.Log;
import androidx.databinding.ViewDataBinding;
import java.util.Timer;
import java.util.TimerTask; public class Click {
ViewDataBinding binding;
private Timer timer; public void onStartClick(final Data data){
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
if (--data.value < ){
cancel();
return;
}
Log.e("ActivityMainBinding","data : " + data);
data.key = "left";
// binding.setData(data);
// binding.notifyChange();
// binding.notifyPropertyChanged(R.id.value);
// binding.value.invalidate();
if (!binding.hasPendingBindings()){
binding.invalidateAll();
}
}
}, * , * );
}
public void onStopClicked(Data data){
cancel();
}
private void cancel(){
if (timer != null){
timer.cancel();
timer = null;
}
}
public Click(ViewDataBinding binding){
this.binding = binding;
}
}
3.3 绑定
package com.example.databind; import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.Fragment; import butterknife.ButterKnife;
import butterknife.OnClick; public class MainFrgmt extends Fragment { ViewDataBinding binding;
private Data data; private void init(){
data = new Data("time", );
binding.setVariable(BR.data,data);
binding.setVariable(BR.click,new Click(binding));
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater,R.layout.frgmt_main,container,false);
View view = binding.getRoot();
ButterKnife.bind(this,view);
init();
return view;
} @OnClick(R.id.reset)
public void onResetClicked(View view){
data.key = "time";
data.value = ;
binding.invalidateAll();
}
}
其中:
- 第31行创建绑定对象 binding
- 第24、25行设置绑定的数据对象,其中的BR是绑定库生成的一个类,其中包含<data>中声明的变量的id。如data的id就是BR.data
- 第41行更新数据对象
4.Item绑定数据源
4.1 item布局
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"> <data>
<variable name="item" type="com.example.databind.list.ItemData" />
</data> <LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<ImageView
android:id="@+id/item_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
app:imageSrc="@{item.icon}" />
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="5"
android:layout_marginLeft="32dp"
android:layout_marginStart="32dp"
android:layout_marginRight="8dp"
android:layout_marginEnd="8dp"
android:layout_gravity="center_vertical"
android:gravity="left|center_vertical"
android:textAllCaps="false"
android:textSize="16sp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:text="@{item.title,default = item}" />
</LinearLayout> </layout>
4.2 数据类
package com.example.databind.list; public class ItemData {
public String title;
public int icon;
}
4.3 adapter
package com.example.databind.list; import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView; import androidx.annotation.NonNull;
import androidx.databinding.BindingAdapter;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView; import com.example.databind.R;
import com.example.databind.databinding.ListItemBinding; import java.util.ArrayList;
import java.util.List; public class ListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private List<ItemData> datas = new ArrayList<>(); public void initData(){
for (int i = ; i < ; ++i){
ItemData item = new ItemData();
item.title = "item" + i;
switch (i){
case : case : case :
case : item.icon = R.mipmap.icon1; break; case : case : case :
case : item.icon = R.mipmap.icon2; break; case : case : case :
case : item.icon = R.mipmap.icon3; break; case : case : case :
case : item.icon = R.mipmap.icon4; break; case : case : case :
case : item.icon = R.mipmap.icon5; break; case : case :
case : item.icon = R.mipmap.icon6; break; case : case :
case : item.icon = R.mipmap.icon7; break; case : case :
case : item.icon = R.mipmap.icon8; break; case : case :
case : item.icon = R.mipmap.icon9; break;
default: item.icon = R.mipmap.icon0; break;
}
datas.add(item);
}
} @BindingAdapter({"imageSrc"})
public static void setImage(ImageView view, int icon){
view.setImageResource(icon);
} @NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.list_item,parent,false);
BindHolder holder = new BindHolder(view); return holder;
} @Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
BindHolder bh = (BindHolder) holder;
ItemData item = datas.get(position);
ListItemBinding binding = DataBindingUtil.bind(bh.itemView);
binding.setItem(item);
} @Override
public int getItemCount() {
return datas.size();
} public static class BindHolder extends RecyclerView.ViewHolder{ public BindHolder(@NonNull View itemView) {
super(itemView);
}
}
}
5.ActivityMainBinding 等绑定类哪来的?
5.1 他们是绑定框架生成的接口
位置:
以 Frgmt1Binding 为例,它的实现在 : app\build\generated\ap_generated_sources\debug\out\com\example\databind\databinding 目录下,
com\example\databind 是包名,如下:
默认的命名规则:
布局文件名按Pascal命名方法(忽略下划线_) + Binding , 如布局文件是 Frgmt1.xml 那么生成的类就是 Frgmt1Binding
5.2 代码
package com.example.databind.databinding;
import com.example.databind.R;
import com.example.databind.BR;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.View;
@SuppressWarnings("unchecked")
public class Frgmt1BindingImpl extends Frgmt1Binding { @Nullable
private static final androidx.databinding.ViewDataBinding.IncludedLayouts sIncludes;
@Nullable
private static final android.util.SparseIntArray sViewsWithIds;
static {
sIncludes = null;
sViewsWithIds = new android.util.SparseIntArray();
sViewsWithIds.put(R.id.imageView, );
sViewsWithIds.put(R.id.textView, );
}
// views
@NonNull
private final androidx.constraintlayout.widget.ConstraintLayout mboundView0;
// variables
// values
// listeners
// Inverse Binding Event Handlers public Frgmt1BindingImpl(@Nullable androidx.databinding.DataBindingComponent bindingComponent, @NonNull View root) {
this(bindingComponent, root, mapBindings(bindingComponent, root, , sIncludes, sViewsWithIds));
}
private Frgmt1BindingImpl(androidx.databinding.DataBindingComponent bindingComponent, View root, Object[] bindings) {
super(bindingComponent, root,
, (android.widget.ImageView) bindings[]
, (android.widget.TextView) bindings[]
, (android.widget.TextView) bindings[]
, (android.widget.TextView) bindings[]
);
this.key.setTag(null);
this.mboundView0 = (androidx.constraintlayout.widget.ConstraintLayout) bindings[];
this.mboundView0.setTag(null);
this.value.setTag(null);
setRootTag(root);
// listeners
invalidateAll();
} @Override
public void invalidateAll() {
synchronized(this) {
mDirtyFlags = 0x4L;
}
requestRebind();
} @Override
public boolean hasPendingBindings() {
synchronized(this) {
if (mDirtyFlags != ) {
return true;
}
}
return false;
} @Override
public boolean setVariable(int variableId, @Nullable Object variable) {
boolean variableSet = true;
if (BR.click == variableId) {
setClick((com.example.databind.Click) variable);
}
else if (BR.data == variableId) {
setData((com.example.databind.Data) variable);
}
else {
variableSet = false;
}
return variableSet;
} public void setClick(@Nullable com.example.databind.Click Click) {
this.mClick = Click;
}
public void setData(@Nullable com.example.databind.Data Data) {
this.mData = Data;
synchronized(this) {
mDirtyFlags |= 0x2L;
}
notifyPropertyChanged(BR.data);
super.requestRebind();
} @Override
protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
switch (localFieldId) {
}
return false;
} @Override
protected void executeBindings() {
long dirtyFlags = ;
synchronized(this) {
dirtyFlags = mDirtyFlags;
mDirtyFlags = ;
}
java.lang.String stringValueOfDataValue = null;
java.lang.String dataKey = null;
com.example.databind.Data data = mData;
int dataValue = ; if ((dirtyFlags & 0x6L) != ) { if (data != null) {
// read data.key
dataKey = data.key;
// read data.value
dataValue = data.value;
} // read String.valueOf(data.value)
stringValueOfDataValue = java.lang.String.valueOf(dataValue);
}
// batch finished
if ((dirtyFlags & 0x6L) != ) {
// api target 1 androidx.databinding.adapters.TextViewBindingAdapter.setText(this.key, dataKey);
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.value, stringValueOfDataValue);
}
}
// Listener Stub Implementations
// callback impls
// dirty flag
private long mDirtyFlags = 0xffffffffffffffffL;
/* flag mapping
flag 0 (0x1L): click
flag 1 (0x2L): data
flag 2 (0x3L): null
flag mapping end*/
//end
}
5.3 可以直接使用 ViewDataBinding
private ViewDataBinding binding; private void init(View view){
binding = DataBindingUtil.bind(view);
MainActivity main = (MainActivity) getActivity();
binding.setVariable(BR.data,main.data);
}
android 数据绑定(1)Ativity、Fragment、Item绑定数据源的更多相关文章
- 【Android UI】:Fragment官方文档
概述 Fragment表现Activity中UI的一个行为或者一部分.可以将多个fragment组合在一起,放在一个单独的activity中来创建一个多界面区域的UI,并可以在多个activity ...
- Android开发-API指南-Fragment
Fragments 英文原文:http://developer.android.com/guide/components/fragments.html 采集日期:2014-12-31 在本文中 设计理 ...
- Android数据绑定技术一,企业级开发
PS:数据绑定,顾名思义是数据与一些控件或者用户账号等绑定,这样用的好处是便于管理.代码清晰,量少. 首先要了解什么是数据绑定? 为什么要用数据绑定? 怎么用数据绑定? 语法的使用 简单例子,数据绑定 ...
- Android数据绑定技二,企业级开发
PS:上一篇文章写了Databinding的简单使用,写了一个绑定textview的示例,和绑定的一些用法,估计有的人会说,之前的写的好好的,为什么要数据绑定这样的写法呢,没办法,社会在进步,当然是怎 ...
- Android开发工程师文集-Fragment,适配器,轮播图,ScrollView,Gallery 图片浏览器,Android常用布局样式
Android开发工程师文集-Fragment,适配器,轮播图,ScrollView,Gallery 图片浏览器,Android常用布局样式 Fragment FragmentManager frag ...
- Android数据绑定技术二,企业级开发
PS:上一篇文章写了Databinding的简单使用,写了一个绑定textview的示例,和绑定的一些用法,估计有的人会说,之前的写的好好的,为什么要数据绑定这样的写法呢,没办法,社会在进步,当然是怎 ...
- Android数据绑定DataBinding(一)入门篇
早上看到了一篇推文"还在使用繁琐的findViewById,跟着尝试了一下DataBinding,之前使用ButteKnife就已经干掉了findViewById.因为写过微信小程序,那种在 ...
- C# DataGridView绑定数据源的几种常见方式
开始以前,先认识一下WinForm控件数据绑定的两种形式,简单数据绑定和复杂数据绑定. 1. 简单的数据绑定 例1 using (SqlConnection conn = new SqlConnect ...
- wemall app商城源码Android 获取XML网络数据并绑定到ListView
wemall-mobile是基于WeMall的android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享Android 获取XML网络数据并绑定到Li ...
随机推荐
- iOS开发系列-NSOutputStream
NSOutputStream 创建一个NSOutputStream实例 - (nullable instancetype)initToFileAtPath:(NSString *)path appen ...
- js闭包与java内部类
在js中闭包用的比较广泛,主要解决变量作用域导致的问题.
- SoapUI测试接口【转】
下载安装soapUI工具,具体安装按照提示往下走就可以,这里不着重说明,下面是我打开soapUI工具的起始窗口: 在Projects上鼠标右键点击,选择new soap project(新建一个SO ...
- python类的静态方法和类方法区别
先看语法,python 类语法中有三种方法,实例方法,静态方法,类方法. # coding:utf-8 class Foo(object): """类三种方法语法形式&q ...
- PAT甲级——A1071 Speech Patterns
People often have a preference among synonyms of the same word. For example, some may prefer "t ...
- [原创]新版PageOffice V4.0为什么用弹出窗口的方式打开文件?
前的包含文档处理功能的Web办公系统,在打开文档的时候,一部分系统是采用Office文档嵌入到主窗口页面中右侧工作区域的方式,另一部分系统采用的是弹出新的浏览器窗口,里面完整的嵌入Office文件的打 ...
- 定时ping取返回值并绘图
figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...
- stylus实现边框1px
//1px的实现 border($border-width = 1px, $border-color = #ccc, $border-style = solid, $radius = ) // 为边框 ...
- Windows API 第15篇 GetVolumeInformation 获取磁盘卷(驱动器)信息
先看定义:BOOL GetVolumeInformation( [IN] LPCTSTR lpRootPathName, // root directory 卷所在的根目 ...
- CSS 滤镜效果
本文所描述的滤镜,指的是 CSS3 出来后的滤镜,不是 IE 系列时代的滤镜,语法如下,还未接触过这个属性的可以先简单到 MDN -- filter 了解下: { filter: blur(5px); ...