DataBinding学习笔记(一)源码分析

Jetpack ---- DataBinding完全解析(三)DataBinding使用及源码分析 此篇博客转载自 csdn小瓯 Jetpack ---- DataBinding完全解析(三)DataBinding使用及源码分析介绍APT预编译布局的格式和处理关联Activity组件与布局何时生成设置Model帮助类?实战引入定义实体类定义Layout布局Rebuild Project书写代码绑定 DataBinding是一种工具,能在编译时绑定布局和对象。通过这篇文章,一是要掌握DataBinding的使用,二是我们要弄懂,View层是怎么改变Model的,而Model层又是如何改变View的。 介绍 阅读详情

###DataBinding整体使用流程
在这里插入图片描述

###开发阶段
#####UserModel.java

public class UserModel {
    public String name;
    public String nickName;
    public int age;

    public UserModel(String name, String nickName, int age) {
        this.name = name;
        this.age = age;
        this.nickName = nickName;
    }

    public boolean isAge18() {
        return age >= 18;
    }
}

#####activity_main.xml

在xml中使用"@{}"标识符

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <variable name="user" type="com.listen.test_databinding.UserModel"/>
        <variable name="testClick" type="android.view.View.OnClickListener"/>
        <import type="android.view.View"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.listen.test_databinding.MainActivity">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{"名字" + user.name}'/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{user.nickName}'
            android:visibility="@{null == user.nickName ? View.VISIBLE : View.GONE}"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{user.isAge18() ? "man" : "boy"}'/>

        <Button
            android:id="@+id/btn_test"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:onClick="@{testClick}" android:text="测试"/>
    </LinearLayout>
</layout>

#####MainActivity.java

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding mBinding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        final UserModel user = new UserModel("listen", "ls", 18);
        mBinding.setUser(user);
        mBinding.setTestClick(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this, "testClick", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

###编译阶段

####1.Databinding会自动解析识别xml中的"@{}"标识符,并在以下目录生成2个xml文件

1.build/intermediates/data-binding-layout-out/activity_main.xml
2.build/intermediates/data-binding-info/debug/activity_main-layout.xml

######activity_main.xml

带“@{}”的xml文件是android系统无法识别的,为了向后兼容,需要在编译期统一转换成系统能识别的标准xml布局,而原先在布局中添加的"@{}","@{三目运算符}"等信息,则会存储在activity_main-layout.xml中。

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"    
    android:orientation="vertical"
    android:tag="layout/activity_main_0"
    tools:context="com.listen.test_databinding.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:tag="binding_1"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:tag="binding_2"
    />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:tag="binding_3"/>

    <Button
        android:id="@+id/btn_test"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:tag="binding_4" android:text="测试"/>
</LinearLayout>

######activity_main-layout.xml(xml描述文件)

1.任何view只要用到了"@{}“标识,就会在activity_main-layout.xml中生成target描述,并根据该view在parent中的位置生成"binding_[index]“标识,并设置在tag中。
2.如果一个view即没有设置"android:id”,也没有使用”@{}“标识,则不会在activity_main-layout.xml中生成这个view的target描述。
3.LinearLayout比较特殊,并没有设置"android:id”,也没有使用"@{}",但还是会生成一个默认的tag=“layout/activity_main_0”,表示它是根布局,在ViewDataBinding.java实例化时,需要判断根布局的tag,后面源码会分析到。

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Layout absoluteFilePath="/Users/lisong/Documents/AndroidStudioWorkSpace/Test_Databinding/app/src/main/res/layout/activity_main.xml" directory="layout"
        isMerge="false"
        layout="activity_main" modulePackage="com.listen.test_databinding">
    <Variables name="user" declared="true" type="com.listen.test_databinding.UserModel">
        ...
    </Variables>
    <Variables name="testClick" declared="true" type="android.view.View.OnClickListener">
        ...
    </Variables>
    <Imports name="View" type="android.view.View">
        ...
    </Imports>
    <Targets>
        <Target tag="layout/activity_main_0" view="LinearLayout">
            <Expressions/>
            ...
        </Target>
        <Target tag="binding_1" view="TextView">
            <Expressions>
                <Expression attribute="android:text" text=""名字" + user.name">
                    ...
                </Expression>
            </Expressions>
        </Target>
        <Target tag="binding_2" view="TextView">
            <Expressions>
                <Expression attribute="android:text" text="user.nickName">
                    ...
                </Expression>
                <Expression attribute="android:visibility"
                            text="null == user.nickName ? View.VISIBLE : View.GONE">
                    ...
                </Expression>
            </Expressions>
        </Target>
        <Target tag="binding_3" view="TextView">
            <Expressions>
                <Expression attribute="android:text"
                            text="user.isAge18() ? "man" : "boy"">
                    ...
                </Expression>
            </Expressions>
        </Target>
        <Target id="@+id/btn_test" tag="binding_4" view="Button">
            <Expressions>
                <Expression attribute="android:onClick" text="testClick">
                    ...
                </Expression>
            </Expressions>
        </Target>
    </Targets>
</Layout>

####2.生成ActivityMainBinding.java和BR.java

DataBinding根据解析后的activity_main-layout.xml,和layout下的activity_main.xml文件,生成build/intermediates/classes/debug/[项目路径]/databinding/
ActivityMainBinding.java和BR.java

在这里插入图片描述
######ActivityMainBinding主要具备以下功能

1.作为view和model的连接器,持有需要展示的数据和views的成员变量
2.将数据映射到view(就是setText,setOnClick等)
3.在UI线程更新数据

######BR.java就是一个常量类

可以通过binding.setVariable(BRuser, new User())进行数据更新

public class BR {
    public static final int _all = 0;
    public static final int testClick = 1;
    public static final int user = 2;

    public BR() {
    }
}
public boolean setVariable(int variableId, Object variable) {
    switch(variableId) {
        case BR.testClick :
            setTestClick((android.view.View.OnClickListener) variable);
            return true;
        case BR.user :
            setUser((com.listen.test_databinding.UserModel) variable);
            return true;
    }
    return false;
}

###运行阶段

Databinding框架最主要做的事,就是以上2步,接下来就是在代码中调用生成的ViewDataBinding,并进行数据绑定操作。

######DataBindingUtil是一切的入口

ActivityMainBinding mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
public static <T extends ViewDataBinding> T setContentView(Activity activity, int layoutId, DataBindingComponent bindingComponent) {
    activity.setContentView(layoutId);// 最终调用的还是activity.setContentView(),不过这里的layoutId是已经去掉"@{}"的标准xml布局
    View decorView = activity.getWindow().getDecorView();
    ViewGroup contentView = (ViewGroup) decorView.findViewById(android.R.id.content);//获取根顶级容器view
    return bindToAddedViews(bindingComponent, contentView, 0, layoutId);
}

######取出布局的rootView,调用ActivityMainBinding.bind()

private static <T extends ViewDataBinding> T bindToAddedViews(android.databinding.DataBindingComponent component, ViewGroup parent, int startChildren, int layoutId) {
    final int endChildren = parent.getChildCount();
    final int childrenAdded = endChildren - startChildren;
    if (childrenAdded == 1) {
        // 从顶级容器view中获取当前布局的rootView,调用bind方法
        final View childView = parent.getChildAt(endChildren - 1);
        return bind(component, childView, layoutId);
    } else {
        ...
    }
}

static <T extends ViewDataBinding> T bind(DataBindingComponent bindingComponent, View root,
                                          int layoutId) {
    // sMapper = DataBinderMapper.java
    return (T) sMapper.getDataBinder(bindingComponent, root, layoutId);
}

/**  DataBinderMapper.java */
public android.databinding.ViewDataBinding getDataBinder(android.databinding.DataBindingComponent bindingComponent, android.view.View view, int layoutId) {
    switch(layoutId) {
        case com.listen.test_databinding.R.layout.activity_main:
            // 将rootView传递给ActivityMainBinding.bind()
            return com.listen.test_databinding.databinding.ActivityMainBinding.bind(view, bindingComponent);
    }
    return null;
}

此处做了rootView的判断,如果传递过来的不是当前ViewDataBinding绑定的布局,则抛异常。所以即使rootView没有设置id,及"@{}",在info-layout.xml中也会生成相应的target描述。

public static ActivityMainBinding bind(View view, DataBindingComponent bindingComponent) {
    if(!"layout/activity_main_0".equals(view.getTag())) {
        throw new RuntimeException("view tag isn\'t correct on view:" + view.getTag());
    } else {
        return new ActivityMainBinding(bindingComponent, view); // ActivityMainBinding在此处初始化
    }
}

这里需要特别注意的是在编译期自动生成的activity_main.xml文件中自动添加了tag=“binding_1”,"binding_2"等,其实在初始化完这些view后,都已经清空,是不影响我们在代码中设置tag的;不过rootView并没有清除tag(就是xml布局最外层的layout),如果>=14以上版本,在代码里设置setTag(R.id.databinding,“anything”),或,<14版本,在代码里设置setTag(“anything”),则会报错,so,这个tag是由DataBinding占着的,使用上得小心。

public ActivityMainBinding(android.databinding.DataBindingComponent bindingComponent, View root) {
    super(bindingComponent, root, 0);
    // 遍历布局,找到所有views,并存储在bindings[]中,5表示布局一共有5个view,sIncludes存储被include进     // 来的布局,sViewsWithIds存储设置了"android:id",但是没有用到"@{}"的view
    Object[] bindings = mapBindings(bindingComponent, root, 5, sIncludes, sViewsWithIds);

    // 将bindings[]中的view取出,赋值给当前各个view的成员变量,并清除tag,避免冲突
    this.btnTest = (Button)bindings[4];
    this.btnTest.setTag((Object)null);
    this.mboundView0 = (LinearLayout)bindings[0];
    this.mboundView0.setTag((Object)null);
    this.mboundView1 = (TextView)bindings[1];
    this.mboundView1.setTag((Object)null);
    this.mboundView2 = (TextView)bindings[2];
    this.mboundView2.setTag((Object)null);
    this.mboundView3 = (TextView)bindings[3];
    this.mboundView3.setTag((Object)null);
    this.setRootTag(root);
    /**
    ViewDatabBinding.java
    protected void setRootTag(View view) {
        //private static final boolean USE_TAG_ID = DataBinderMapper.TARGET_MIN_SDK >= 14;
        if (USE_TAG_ID) {
        view.setTag(R.id.dataBinding, this);
        } else {
        view.setTag(this);
        }
    }
    */

    
    // 请求刷新,实现数据与view的绑定
    this.invalidateAll();
}

mapBindings(),其实就是递归遍历view树的过程,不过不是byId,而是byTag,寻找以"binding_"开头的view,并取出"binding_[索引]"中的索引,赋值给binding[]数组。所有的view只在一次遍历中获得,而如果是用findViewById的方式,每次调用都需要遍历一次view树[性能对比]。需要特别注意的是binding数组的元素不一定都是view或viewGroup,如果有include布局的时候binding数组存储的可能是include布局的viewDataBinding对象。

private static void mapBindings(DataBindingComponent bindingComponent, View view, Object[] bindings, ViewDataBinding.IncludedLayouts includes, SparseIntArray viewsWithIds, boolean isRoot) {
    ViewDataBinding existingBinding = getBinding(view);
    if(existingBinding == null) {
        Object objTag = view.getTag();
        String tag = objTag instanceof String?(String)objTag:null;
        
        if(isRoot && tag != null && tag.startsWith("layout")) {
            // 如果是rootView,则从"layout/activity_main_0"中取出索引"0",设置到bindings[0]中
            viewGroup = tag.lastIndexOf(95);
            count = parseTagInt(tag, viewGroup + 1);
            if(bindings[count] == null) {
                bindings[count] = view;
            }
            ...
        } else if(tag != null && tag.startsWith("binding_")) {
            // 同样判断tag,取出"binding_1","bingding_2"中的索引,赋值到bindings[]中
            viewGroup = parseTagInt(tag, BINDING_NUMBER_START);
            if(bindings[viewGroup] == null) {
                bindings[viewGroup] = view;
            }
            ...
        }
        
        // isBound=false,说明当前的view既不是根布局,也没有用到"@{}"(如果有用到就会生成"binding_"
        // 的tag);则通过id获取该view,并设置到bingding[]
        // 如果存在设置了id,但是没有“@{}”的view会被添加到sViewsWithIds中,如果
        // "binding_[index]"的index最大为3,则view的起始index设置为4。
        // static {
        //    sIncludes = null;
        //    sViewsWithIds = new android.util.SparseIntArray();
        //    sViewsWithIds.put(R.id.btn_test, 4);
        //}
        if(!isBound) {
            viewGroup = view.getId();
            if(viewGroup > 0 && viewsWithIds != null && (count = viewsWithIds.get(viewGroup, -1)) >= 0 && bindings[count] == null) {
                bindings[count] = view;
            }
        }

        if(view instanceof ViewGroup) {
            // 如果是view是个viewGroup,则遍历子view
            ViewGroup var25 = (ViewGroup)view;
            count = var25.getChildCount();
            ...

            for(int i = 0; i < count; ++i) {
                View child = var25.getChildAt(i);
                boolean isInclude = false;
                if(indexInIncludes >= 0 && child.getTag() instanceof String) {
                    String childTag = (String)child.getTag();
                    if(childTag.endsWith("_0") && childTag.startsWith("layout") && childTag.indexOf(47) > 0) {
                        // 如果当前view也是一个rootView,则判断tag中是否有include标识信息
                        // 如果包含include标签,生成的info-layout文件应该是以下样式:
                        // <Target include="include_main" tag="layout/activity_main_0">
                        // </Target>
                        int includeIndex = findIncludeIndex(childTag, minInclude, includes, indexInIncludes);
                        if(includeIndex >= 0) {
                            isInclude = true;
                            ...
                            // 如果包含include信息,则重新调用DataBindingUtil.bind()生成ViewDataBinding,重复当前流程,
                            // 不过当前的bindings[index]就不是一个view,而是一个viewDataBinding
                            bindings[index] = DataBindingUtil.bind(bindingComponent, child, layoutId);
                            ...
                        }
                    }
                }

                if(!isInclude) {
                    // 如果只是一个viewGroup,不是include进来的布局,则重新调用mapBindings,只是isRoot=false,则会上面进入"binding_"的判断逻辑
                    mapBindings(bindingComponent, child, bindings, includes, viewsWithIds, false);
                }
            }
        }

    }
}

#####view遍历流程图
在这里插入图片描述

View都找到了,现在该是时候设置listener,data的时候了。这时候会通过invalidateAll()请求数据更新,层层调用后,还是回到了ActivityMainBinding的executeBindings(),在这个方法里将更新后的model数据,onclick等重新设置到Textview,Button上,完成了model->view的单向绑定。


// 子类:xxxViewDataBinding extends ViewDataBinding
public void invalidateAll() {
    synchronized(this) {
        this.mDirtyFlags = 4L;
    }

    this.requestRebind();
}

// 父类:ViewDataBinding.java
// 通过handler.post()执行mRebindRunnable
protected void requestRebind() {
    ...
    mUIThreadHandler.post(mRebindRunnable);
}

// mRebindRunnable调用了executePendingBindings()
private final Runnable mRebindRunnable = new Runnable() {
    @Override
    public void run() {
        ...
        executePendingBindings();
    }
};

// executePendingBindings调用了executeBindings()
public void executePendingBindings() {
    ...
    executeBindings();
    ...
}

// 子类:xxxViewDataBinding extends ViewDataBinding
protected void executeBindings() {
    ...
    // 当调用ViewDataBinding.setUser(new User())时,就是给成员变量mUser赋值,在这里获取this.mUser
    UserModel user = this.mUser;

    if((dirtyFlags & 6L) != 0L) {
        // 获取并构建数据,所以model中的字段要么为public,要么提供一个getter方法,不然这里无法获取
        // 可以看到,在xml中的@{}表达式,此时已经解析成对应的方法isAge18,user.name等
        if(user != null) {
            userIsAge18User = user.isAge18();
            nameUser = user.name;
            nickNameUser = user.nickName;
        }

        ...
        // 获取并构建数据
        userIsAge18UserStrin = userIsAge18User?"man":"boy";
        stringNameUser = "名字" + nameUser;
        ObjectnullNickNameUs1 = null == nickNameUser;
        ...

        objectnullNickNameUs = ObjectnullNickNameUs1?0:8;
    }

    // 设置listener
    if((dirtyFlags & 5L) != 0L) {
        this.btnTest.setOnClickListener(testClick);
    }

    // 通过TextViewBindingAdapter将数据设置到TextView上
    if((dirtyFlags & 6L) != 0L) {
        TextViewBindingAdapter.setText(this.mboundView1, stringNameUser);
        TextViewBindingAdapter.setText(this.mboundView2, nickNameUser);
        this.mboundView2.setVisibility(objectnullNickNameUs);
        TextViewBindingAdapter.setText(this.mboundView3, userIsAge18UserStrin);
    }

}

######以上便是当我们通过DataBindingUtil.setContentView()对Databinding进行初始化,以及当我们获取到最新数据,通过Binding.setModel进行数据更新时的操作流程。
在这里插入图片描述

###参考

英文官方文档
https://developer.android.com/topic/libraries/data-binding/index.html

Google开发团队介绍DataDinding使用
https://realm.io/cn/news/data-binding-android-boyar-mount/?utm_source=tuicool&utm_medium=referral

QQ音乐团队分享,比较贴近源码的介绍
http://gold.xitu.io/entry/57e48e7ba22b9d006139c60b

安卓入门十五 常用功能模块一DataBinding 在 ViewModel 中使用了 LiveData 后 , 必须调用 LiveData#observe 函数 为 LiveData 设置 androidx.lifecycle.Observer 监听器 , 如果 监听到了 LiveData 数据变化 , 直接 回调 监听器的 androidx.lifecycle.Observer#onChanged 函数 , 在该回调函数中执行 更新视图 操作;为 Button 组件设置点击事件时 , 如果要 调用配置的 ViewModel 对象的函数 , 需要使用。 阅读详情

相关推荐

滚动时域优化方法

滚动时域优化(Receding Horizon Optimization, RHO),也被广泛称为模型预测控制(Model Predictive Control, MPC),是一种用于动态系统优化和控制的。其核心思想是“在每个当前时刻k,控制器只考虑未来一个(称为“预测时域”或“优化时域”,长度N)内的系统行为。(通过测量或估计得到)。(描述状态如何随输入和干扰变化)。(如果有,可能基于历史数据或假设)。在这个有限的未来时域[k, k+N-1]上,求解一个。这个优化问题的目标是找到一个。

m0_69522810的博客 2300

jetpack之数据绑定的源码解读(二)

源码版本:Android10 在上一篇jetpack之数据绑定的源码解读(一)中介绍了DataBinding的基本原理,这篇文章主要是讲@InverseBindingAdapter以及是如何实现双向绑定的。 一、Demo源码 1.1 activity_recycler_view.xml源码 <?xml version="1.0" encoding="utf-8"?> <layout> <data> <variable

Duckdan的博客 266

Golang中使用Qt库(therecipe/qt)+QtDesigner + Goland (一) 环境搭建

搭建的目的只是刚好看到有这么一个模块, 还有给使用Go的人需要用到调试界面的时候用一下,真正开发界面并不建议用,没必要, 还有缺点就是在windows平台下编译偏慢, 还有其他一些UI纯Go开发的UI -

听我一言的博客 1万+

Databinding 使用以及相关问题

DataBinding 官方文档的解释:数据绑定库是一个支持库,允许您使用声明性格式而不是以编程方式将布局中的UI组件绑定到应用程序中的数据源。其实已经出来很久了,但是身边朋友使用的人不是特别多,今天出一个使用教程: 优点:DataBinding的优点比普通的findViewById之后再设置数据简单了很多,并且数据更新也很简单只要更新绑定的binding,数据更新会自动生效 官方文档 下面介...

nanxuan521的专栏 2419

网格聚类 Grid Clustering/Grid-based Clustering

本文主要简单介绍了网格聚类的基本概念,优缺点,应用场景,建模时的注意事项,评价指标,实现方法,python示例和模型参数等。

JasonH2021的博客 4828

海康Visionmaster-通讯管理:使用 Modbus TCP 通讯 协议与流程交互

海康Visionmaster-通讯管理:使用 Modbus TCP 通讯 协议与流程交互

视觉人机器视觉的博客 9182

DataBinding 学习

目录目录 一环境搭建 Android 的 Gradle 插件版本不低于 150-alpha1 修改对应模块app的 buildgrade 二基本使用 布局文件 数据对象 定义 Variable 自定义Binding类名称 绑定 Variable 使用 Variable 三高级用法 使用类方法 类型别名 Null Coalescing 运算符 空合并运算符 属性值 使用资源数据 Observable

u012438968的博客 401

【Linux】软件控制USB重新上电、加载:usbreset、hubpower、uhubctl

使用命令控制USB的供电、复位

郭老二 2188

android开发之DataBinding的使用以及源码深度分析

本文详细介绍了DataBinding的使用、DataBinding的原理以及DataBinding源码的深度分析

Jesiah的博客 1929

Vue - 最新详细实现滑块拖动拼图验证,网站登录验证滑块验证功能,拖动滑块到图片缺口的位置即为成功,滑块验证安全检测(详细示例代码,一键复制运行)

您一定见过很多系统都“配备”了滑块验证、拼图验证、找不同等,本质上都是为了验证登录系统的是人还是机器(代码),如下图所示效果: 您打开项目根目录,终端执行如下命令:拼图式拖动滑块验证 验证拖动滑块验证,滑动拼图/图片点选验证 接下来,在中加入以下代码: 如下图所示: 更多配置示例和参数详见官方文档,以下便是如上效果图的代码:.........

🏆 前端领域优质创作者 1万+

配置 SAP ABAP Secure Storage

系统在进行数据加密时,会将数据与当前 Key ID 进行关联,也就是说,如果此时使用的是 Key ID 4713,则该条数据会在 Encrypt.Data 字段存储一个由密钥 4713 加密后的密文。Key ID 代表了不同的密钥标识,Current Key 表示系统当前正在使用的主密钥,Value 则是对应密钥的存储值,Management Data 通常包括一些管理性或辅助性的信息,用于描述密钥的状态、过期时间或者其他属性。对于每一条被加密的业务数据,系统会记录它使用了哪一条 Key ID。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 566

DataBining从基本使用到核心源码解析,看不懂的兄弟跟我一起去摆摊(1)

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

2301_82242426的博客 393

PyQt5简介和安装

在initUI方法中,设置了窗口的标题和大小,并创建了一个按钮。PyQt5是一个功能强大的Python界面开发框架,可以轻松创建跨平台的图形用户界面应用程序。本文介绍了PyQt5的简介和安装方法,并提供了一个简单的示例应用程序来演示PyQt5的基本用法。PyQt5是一个功能强大的Python界面开发框架,它提供了丰富的工具和组件,用于创建跨平台的图形用户界面(GUI)应用程序。信号是控件发出的事件,槽是与之关联的处理函数。接下来,我们将编写一个简单的PyQt5应用程序,以演示PyQt5的基本用法。

XdKwargs的博客 225

JetPack DataBinding源码分析

DataBinding是谷歌15年推出的一个工具支持库,借助该库可以使用声明性格式将布局中的界面组件绑定到应用中的数据源。DataBinding支持双向绑定,能大大减少绑定app逻辑与layout 文件的“胶水代码”,例如setText、findViewById等代码。双向绑定,即数据发生变化时界面跟着变化,反过来界面内容变化也会同步更新到数据上。

永琪的博客 1823

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Android 安卓DataBinding(一)·基础

文章目录前言DataBinding介绍开始准备快捷按键实例代码(基本用法)运行效果 前言 今天2019年9月29日,本人优快云博客 称号 博客专家 审核通过了,为了庆祝,特此今天写一篇博客作为纪念! 欢迎扫描左方二维码(群号码:697614838),加入我的优快云粉丝群(请备注好你的专业)! DataBinding介绍 DataBinding 是谷歌官方发布的一个框架,其作用是实现数据绑定(...

两行代码 踏踏实实de工作 1万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

DataBinding的使用一

文章目录一、前言二、环境配置三、将现有布局转换为databinding布局四、数据绑定五、DataBinding文件六、参考链接 一、前言 `DataBinding`是`JetPack`中用来进行双向绑定的库,可以使数据和UI进行解耦合。这里对其进行使用进行简单的记录 二、环境配置 在以前的旧版上使用`DataBinding`还需要添加插件和依赖库,不过目前来说无需如此复杂,只需要在`build.gradle`中进行简单的配置即可。这里有两种配置方式,如下: 方式一: android {

Mr_Tony的专栏 4237

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Databinding使用、Databinding原理、Androidx集成Databinding、Databinding源码分析、Databinding双向绑定原理

简介 Databinding是谷歌的一个官方支持库,它允许您使用声明性格式而不是通过编程方式将布局中的UI组件绑定到应用程序中的数据源。 通常在活动中使用调用UI框架方法的代码来定义布局。例如,调用findViewById()以查找TextView窗口小部件并将其绑定到变量。 因为它通过在布局文件中绑定组件,您可以删除活动中的许多UI框架调用,从而使它们更易于维护。这也可以提高应用程序的性能,并有...

archie_7的博客 2439

databinding源码分析一

前言databinding是google在2015年发布的一个库,支持布局文件和mode数据之间进行绑定。最新版本已经支持双向绑定,数据的更新可以触发同步到布局对应的ui界面,布局文件的数据更新也可以传递到mode数据上。1. 数据更新如何触发ui更新的?2. ui操作是如何关联上数据的?3. 自定义view该如何关联数据绑定?带着以上三个问题分析源码,本篇先分析问题一: databinding源

读书未遍、未敢妄下雌黄 947

学习笔记:DataBinding(一):上手DataBinding

DataBinding是什么 数据绑定库是一种支持库,借助该库,您可以使用声明性格式(而非程序化地)将布局中的界面组件绑定到应用中的数据源。 使用DataBinding之前: findViewById<TextView>(R.id.sample_text).apply { text = viewModel.userName } 使用DataBindin...

编码之路 1133

Jetpack之DataBinding

(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总)面试成功其实是必然的,因为我做足了充分的准备工作,包括刷题啊,看一些Android核心的知识点,看一些面试的博客吸取大家面试的一些经验,

2401_84132357的博客 494

Android之Databinding学习笔记

Android之DataBinding学习笔记简介Data binding 在2015年7月发布的Android Studio v1.3.0 版本上引入,在2016年4月Android Studio v2.0.0 上正式支持。目前为止,Data Binding 已经支持双向绑定了。Databinding 是一个实现数据和UI绑定的框架,是一个实现 MVVM 模式的工具,有了 Data Binding

GodV的博客 2690

DataBinding的源码分析

简介 前面的博客我已经说过了关于DataBinding的基本使用,这一章节主要介绍它的原理

nity_的博客 700

Android架构之DataBinding(一)

DataBinding的意义和优势 我们知道,一般对控件进行操作,都是通过UI控件的id找到控件,接在再页面中通过代码对控件进行操作。 比如以下代码通过findViewById()来查找TextView控件并将其绑定到viewModel变量的userName属性. TextView textView = findViewById(R.id.sample_text); textView.setText(viewModel.getUserName()); 可以说,在页面中有很多这样类似的代码,使得页面的代码越

qq_43404873的博客 3717

DataBinding为null?模块化开发中的DataBinding你需要注意了

这几天在新的项目开发中使用DataBinding遇到了一个DataBindingUtil.setContentView()返回null的问题,在解决问题的过程中顺便将DataBinding源码分析了一下,这篇文章中的示例可能有些人看不天明白,因为你没有遇到相同的问题,所以感觉很绕,如果有人遇到相同的问题,希望能帮助到你。如果你只是想了解DataBinding的原理,可以直接看中间的两个内容,分别讲解了DataBinding的使用和源码分析。 1. 使用DataBinding遇到的问题 公司项目在18年就全部

openXu的专栏 8291

dataBinding源码分析

上篇写了dataBinding的使用和封装,今天我们就分析下源码。 首先我们从DataBindingUtil.setContentView(this,R.layout.activity_main);方法作为入口,发现最后还是调用activity的setContentView()方法。 //最后会调用bind()方法,这个方法会调用 DataBindingMapper类的getDataBi...

qq_36237165的博客 396

Android DataBinding 笔记一

官网介绍,DataBinding是用于将数据的和视图绑定在一起的支持库,特点是只需要在视图定义的xml中编写绑定信息,减少在代码中的视图于数据的交互逻辑。 这样可以分离数据和视图,减少这两个模块在代码层面上的耦合。 启用功能 在项目的build.gradle中添加如下代码即可: android { ... dataBinding { enabled = true } } 常见问题: DSL element ‘android.dataBinding.enabled’

ItsFated的博客 1918
下一篇: MVC,MVP,MVPVM(一)实践之路
listen2code
博客等级 码龄10年 7粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值