其实说到DataBinding, 不管你使用MVP,MVVM,估计都有用到,数据和View的双向绑定是很爽的,相信很多小伙伴是用的很6,但是原理以及流程不太清楚。今天分享一起学习下DataBinding的相关流程。

举个例子

public class User extends BaseObservable {private String name;private String age;public User(String name, String age) {this.name = name;this.age = age;}@Bindablepublic String getName() {return name;}public void setName(String name) {this.name = name;notifyPropertyChanged(BR.name);}@Bindablepublic String getAge() {return age;}public void setAge(String age) {this.age = age;notifyPropertyChanged(BR.age);}
}

然后修改XML:

<?xml version="1.0" encoding="utf-8"?>
<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><variablename="user"type="com.example.jetpackproject.databinding.User" /></data><LinearLayoutandroid:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".databinding.DatabindingActivity"><TextViewandroid:id="@+id/tv1"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="@{user.name}"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="@{user.age}"/></LinearLayout>
</layout>

最后将两者绑定起来:

    @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_databinding);user = new User("hello", 10 + "");viewDataBinding.setUser(user);new Thread() {@Overridepublic void run() {super.run();for (int i = 0; i < 10; i++) {user.setName(user.getName() + "");//方法2:
//                    viewDataBinding.setVariable(BR.user, user);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}.start();}

上述示例是一个简单的DataBinding的使用,需要注意一点:

通过调用ViewDataBinding的setVariable方法和notifyPropertyChanged效果是一样的,都可以实现数据修改View接着修改的效果。

现在有几个问题,需要考虑下:

  1. View和Data是怎样绑定的?
  2. Data修改,View是怎样修改的?
  3. setVariable和notifyPropertyChanged有什么关系?
  4. DataBinding是怎样避免使用findViewById的?

带着这些问题,开始源码分析流程。 在开始分析之前,看三个东西:

APT自动生成的代码:

当在XML中写完代码之后,编译一下,会自动生成两个XML文件:

上图的路径是:项目跟路径 ——》app ——》build ——》intermediates 。

注意:这里自动生成的XML文件名,是和自己在项目中使用DataBinding的XML的文件名称关联的。

其中第一个XML文件内容格式化之后,就是下面的东西:

在XML文件中,将每个标签都设置了一个tag, 然后这个tag对应这一个View,这个tag和另一个xml文件中的View是一一对应的,通过这个tag可以获取到View对应的相关信息:
换句话说就是,通过上一个XML文件的Tag,对应的去找第二个XML的View相关信息。

自己使用了DataBinding的XML文件生成了两个XML文件,这两个文件的关联关系如上图所示。

根据XML以及注解,同样生成了相应的Java代码:
在这里插入图片描述
DataBindingMapperImpl,BR, 以及XXXBindingImpl 三个文件是自动生成的,XXXBindingImpl对应XML:activity_databinding.xml。其中Activity DatabindingBinding类是ViewDataBinding的实现类。

BR类里面有很多静态常量,这些常量都是添加了Bindable注解的方法:

    @Bindablepublic String getName() {return name;}

知道了这些自动生成的代码,开始带着上述的那四个问题分析流程。

入口setContentView方法

在Activity的onCreate方法内,将XML扔给了DataBindingUtil,并且传入了Activity本身:

    public static <T extends ViewDataBinding> T setContentView(@NonNull Activity activity,int layoutId, @Nullable DataBindingComponent bindingComponent) {// 内部还是调用了Activity的setContentViewactivity.setContentView(layoutId);......//return bindToAddedViews(bindingComponent, contentView, 0, layoutId);}

其实在DataBindingUtil内部还是调用了Activity的setContentView方法,然后又拿着R.id.content的View给了bindToAddedViews作为参数,最终会进入:bind

    static <T extends ViewDataBinding> T bind(DataBindingComponent bindingComponent, View[] roots,int layoutId) {return (T) sMapper.getDataBinder(bindingComponent, roots, layoutId);}

这里的sMapper就是抽象类DataBinderMapper,具体实现类是:DataBinderMapperImpl类,因此执行的是实现类DataBinderMapperImpl的getDataBinder 方法:

 @Overridepublic ViewDataBinding getDataBinder(DataBindingComponent component, View view, int layoutId) {.....return new ActivityDatabindingBindingImpl(component, view);......}

创建了ActivityDatabindingBindingImpl类实例, 然后我们进入构造方法看看初始化了什么东西。

    public ActivityDatabindingBindingImpl(@Nullable androidx.databinding.DataBindingComponent bindingComponent, @NonNull View root) {//通过mapBindings方法获取到XML中所有的View,并且存储到一个数组中this(bindingComponent, root, mapBindings(bindingComponent, root, 3, sIncludes, sViewsWithIds));}private ActivityDatabindingBindingImpl(androidx.databinding.DataBindingComponent bindingComponent, View root, Object[] bindings) {super(bindingComponent, root, 1, (android.widget.TextView) bindings[1]);// 给成员变量View赋值this.mboundView0 = (android.widget.LinearLayout) bindings[0];this.mboundView0.setTag(null);this.mboundView2 = (android.widget.TextView) bindings[2];this.mboundView2.setTag(null);//将标记tag置为nullthis.tv1.setTag(null);setRootTag(root);// listenersinvalidateAll();}

在构造方法中,首先通过调用mapBindings方法获取到所有的子View对象。那么他是怎么获取子View对象的呢?

  private static void mapBindings(DataBindingComponent bindingComponent, View view,Object[] bindings, IncludedLayouts includes, SparseIntArray viewsWithIds,boolean isRoot) {final int indexInIncludes;final ViewDataBinding existingBinding = getBinding(view);if (existingBinding != null) {return;}Object objTag = view.getTag();final String tag = (objTag instanceof String) ? (String) objTag : null;boolean isBound = false;if (isRoot && tag != null && tag.startsWith("layout")) { // XML中的tag是否是layout开头的final int underscoreIndex = tag.lastIndexOf('_');if (underscoreIndex > 0 && isNumeric(tag, underscoreIndex + 1)) {final int index = parseTagInt(tag, underscoreIndex + 1);if (bindings[index] == null) {bindings[index] = view;}indexInIncludes = includes == null ? -1 : index;isBound = true;} else {indexInIncludes = -1;}} else if (tag != null && tag.startsWith(BINDING_TAG_PREFIX)) {int tagIndex = parseTagInt(tag, BINDING_NUMBER_START);if (bindings[tagIndex] == null) {bindings[tagIndex] = view;}isBound = true;indexInIncludes = includes == null ? -1 : tagIndex;} else {// Not a bound viewindexInIncludes = -1;}if (!isBound) { // view是否设置了idfinal int id = view.getId();if (id > 0) {int index;if (viewsWithIds != null && (index = viewsWithIds.get(id, -1)) >= 0 &&bindings[index] == null) {bindings[index] = view;}}}if (view instanceof  ViewGroup) { //是否是ViewGroupfinal ViewGroup viewGroup = (ViewGroup) view;final int count = viewGroup.getChildCount();int minInclude = 0;for (int i = 0; i < count; i++) { //循环每个子Viewfinal View child = viewGroup.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('/') > 0) {// This *could* be an include. Test against the expected includes.int includeIndex = findIncludeIndex(childTag, minInclude,includes, indexInIncludes);if (includeIndex >= 0) {isInclude = true;minInclude = includeIndex + 1;final int index = includes.indexes[indexInIncludes][includeIndex];final int layoutId = includes.layoutIds[indexInIncludes][includeIndex];int lastMatchingIndex = findLastMatching(viewGroup, i);if (lastMatchingIndex == i) {//包含include标签,重新执行交给DataBindingUtil类处理bindings[index] = DataBindingUtil.bind(bindingComponent, child,layoutId);} else {final int includeCount =  lastMatchingIndex - i + 1;final View[] included = new View[includeCount];for (int j = 0; j < includeCount; j++) {included[j] = viewGroup.getChildAt(i + j);}bindings[index] = DataBindingUtil.bind(bindingComponent, included,layoutId);i += includeCount - 1;}}}}if (!isInclude) { //是否包含 标签include。不包含的话,就递归获取viewmapBindings(bindingComponent, child, bindings, includes, viewsWithIds, false);}}}}

上述代码很长,实际上就是通过tag获取对应的View,然后存入到数组bindings中。方法其实就是个递归,如果XML中定义的是ViewGroup类型的,那么就交给DataBindingUtil重新执行之前的操作;如果不包含,那么到最后就递归通过tag继续获取View。

这里的tag,实际上就是之前开头说的那个XML文件,通过tag文件可以对应的获取第二个XML的View的相关信息。

总体来说:这里就做了一件事情,通过tag获取View,并且将View存入到数组中并返回该数组。

返回该数组之后,将数组中的所有子View赋值给成员变量(XML中View有ID的就直接使用ID设置;没有设置ID的就创建成员变量)。

然后执行了invalidateAll方法,该方法可以看作是初始化View上的数据。最终会执行requestRebind方法:

        protected void requestRebind() {//这里判断View是否包含include标签的布局if (mContainingBinding != null) {mContainingBinding.requestRebind();} else {final LifecycleOwner owner = this.mLifecycleOwner;if (owner != null) {Lifecycle.State state = owner.getLifecycle().getCurrentState();if (!state.isAtLeast(Lifecycle.State.STARTED)) {return; // wait until lifecycle owner is started}}synchronized (this) {if (mPendingRebind) {return;}mPendingRebind = true;}//版本兼容区分if (USE_CHOREOGRAPHER) {mChoreographer.postFrameCallback(mFrameCallback);} else { //  我们分析<16的mUIThreadHandler.post(mRebindRunnable);}}}

该方法最后开启了一个线程mRebindRunnable:

    /*** Runnable executed on animation heartbeat to rebind the dirty Views.*/private final Runnable mRebindRunnable = new Runnable() {@Overridepublic void run() {.....executePendingBindings();}};public void executePendingBindings() {if (mContainingBinding == null) { // 由于我们的XML没有包含include标签,因此进入此判断executeBindingsInternal();} else {mContainingBinding.executePendingBindings();}}private void executeBindingsInternal() {.......executeBindings();.......}

最终进入executeBindings方法,该方法是个抽象方法,其实现是在:ViewDataBinding的实现类ActivityDatabindingBindingImpl。

注意:这里是ActivityDatabindingBindingImpl, 这个自动生成的类是根据你的XML变化的。比如:如果你定义的是abc.xml,那么生成的实现类就是:AbcBindingImpl。

    @Overrideprotected void executeBindings() {......if ((dirtyFlags & 0xfL) != 0) {if ((dirtyFlags & 0xbL) != 0) {if (user != null) {// read user.nameuserName = user.getName(); // 通过调用注解Bindable的方法,获取值}}if ((dirtyFlags & 0xdL) != 0) {if (user != null) {// read user.ageuserAge = user.getAge();}}}// batch finishedif ((dirtyFlags & 0xdL) != 0) {// api target 1 TextView设置值androidx.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView2, userAge);}if ((dirtyFlags & 0xbL) != 0) {// api target 1androidx.databinding.adapters.TextViewBindingAdapter.setText(this.tv1, userName);}}

最终调用了TextViewBindingAdapter的setText方法:

    @BindingAdapter("android:text")public static void setText(TextView view, CharSequence text) {.....//给TextView设置valueview.setText(text);}

至此setContentView流程就分析完了,重新捋一遍:
首先创建了XXXBindingImpl类,然后在构造方法中,通过tag获取到了所有的子view,并且添加到了一个数组中,并且将数组中的每一个值都赋值给了成员变量,或者直接通过ID设置了值。 接下来就是给View初始化数据, 通过通过开启一个线程,最后通过XXXBindingAdapter成功初始化了View。

通过上述流程分析,就解决了问题1 和 问题4

当我们有数据变化时,会直接调用:

viewDataBinding.setVariable(BR.user, user);

已setVariable为入口看下内部是怎么实现View的修改的。

setVariable方法

    @Overridepublic boolean setVariable(int variableId, @Nullable Object variable)  {boolean variableSet = true;if (BR.user == variableId) { // 如果 BR.user == 传入的ID// 调用了setUser方法setUser((com.example.jetpackproject.databinding.User) variable);}else { // 否则直接返回variableSet = false;}return variableSet;}

通过上述代码我们可以得出两点:

  1. 如果传入的是:BR.user(也就是继承BaseObservable),那么就调用方法;
  2. 如果不是就直接返回,那么也就是说:setVariable(BR.name, “hello”);是无效的!!!

继续深入:

    public void setUser(@Nullable com.example.jetpackproject.databinding.User User) {//更新注册updateRegistration(0, User);this.mUser = User;synchronized(this) {mDirtyFlags |= 0x1L;}//这里调用了notifyPropertyChanged方法,(先不要管参数)notifyPropertyChanged(BR.user);super.requestRebind();}

首先调用了updateRegistration方法,这方法就是给每一个BR下的静态常量添加一个监听器:

    protected boolean updateRegistration(int localFieldId, Observable observable) {return updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER);}private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {@Overridepublic WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();}};private boolean updateRegistration(int localFieldId, Object observable,CreateWeakListener listenerCreator) {if (observable == null) { // 解绑return unregisterFrom(localFieldId);}//先从数组中获取WeakListener listener = mLocalFieldObservers[localFieldId];if (listener == null) {// 如果数组中没取到,那么就直接创建registerTo(localFieldId, observable, listenerCreator);return true;}if (listener.getTarget() == observable) {return false;//nothing to do, same object}unregisterFrom(localFieldId);registerTo(localFieldId, observable, listenerCreator);return true;}protected void registerTo(int localFieldId, Object observable,CreateWeakListener listenerCreator) {.....//这里的listener是WeakListener类的实例对象, observable就是User的实例对象listener.setTarget(observable);}

首先看下数组mLocalFieldObservers, 这个东西存储的就是监听器(WeakListener),BR文件中的数组一次从0开始,也就是说为每一个BR的常量都存储了个监听器,并且下标索引就是BR中常量的值。

最后调用了监听器的setTarget方法:

       public void setTarget(T object) {unregister();mTarget = object;if (mTarget != null) {mObservable.addListener(mTarget);}}

这里的mObservable就是WeakPropertyListener类的实例对象,

        @Overridepublic void addListener(Observable target) {//target就是我们的User类的实例对象(注意:该方法在父类中)target.addOnPropertyChangedCallback(this);}

addOnPropertyChangedCallback的实现是在BaseObservable类中:

    @Overridepublic void addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {synchronized (this) {if (mCallbacks == null) {mCallbacks = new PropertyChangeRegistry();}}mCallbacks.add(callback);}

由于callback参数也就是WeakPropertyListener本身,因此也就是说User类间接持有了WeakPropertyListener的引用。

回过头在看下,updateRegistration方法之后调用了notifyPropertyChange方法,如果不管参数的前提下,是不是可以理解为:setVariable内部就是调用了notifyPropertyChanged方法呢? 答案是肯定的。

    public void notifyPropertyChanged(int fieldId) {synchronized (this) {if (mCallbacks == null) {return;}}mCallbacks.notifyCallbacks(this, fieldId, null);}

这里的mCallbacks就是PropertyChangeRegistry实例对象,从类BaseObservable的addOnPropertyChangedCallback方法可以看出来:

    public void notifyChange(@NonNull Observable observable, int propertyId) {notifyCallbacks(observable, propertyId, null);}public synchronized void notifyCallbacks(T sender, int arg, A arg2) {......notifyRecurse(sender, arg, arg2);.......}private void notifyRecurse(T sender, int arg, A arg2) {........notifyCallbacks(sender, arg, arg2, startCallbackIndex, callbackCount, 0);}private void notifyCallbacks(T sender, int arg, A arg2, final int startIndex,final int endIndex, final long bits) {....mNotifier.onNotifyCallback(mCallbacks.get(i), sender, arg, arg2);.....}

通过层层调用最终,进入到了notifyCallbacks方法,这里mNotifier就是PropertyChangeRegistry类中的NOTIFIER_CALLBACK常量。
而mCallbacks是一个数组,其内部存储的就是:WeakPropertyListener。

这里mCallbacks存储的数据类型,可以在ViewDataBinding类中找到。在上文分析的类BaseObservable的addOnPropertyChangedCallback方法中。

因此就进入到了WeakPropertyListener的onPropertyChanged方法中:

        @Overridepublic void onPropertyChanged(Observable sender, int propertyId) {ViewDataBinding binder = mListener.getBinder();......binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);}private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {......//修改二进制的标记值boolean result = onFieldChange(mLocalFieldId, object, fieldId);if (result) {// 是否修改了值//最后赋值requestRebind();}}

看到requestRebind方法,就和setContentView流程分析的代码重合了。

实际上总体流程就是Activity,ViewDataBinding, WeakListener, WeakPropertyListener和ViewModel(也就是User), 这四个类是是互相关联的,ViewModel修改了值,是通过WeakPropertyListener ——》 WeakListener——》ViewDataBinding——》Activity 的:
在这里插入图片描述

最后附上一张流程图, 以setVariable为例:
在这里插入图片描述

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. PCL点云类型详解

    点云类型详解数据类型基础类模板类型自定义类型 数据类型 基础类pcl::PointCloudpcl::PointCloud::width:点云宽度 pcl::PointCloud::height:点云高度 pcl::PointCloud::points:点云中包含的点 pcl:`PointCloud<pcl::PointCloud::isOrganized:点云有无组织//有组织点 cl…...

    2024/4/17 3:16:43
  2. 【Java】【转载】使用IntelliJ IDEA编写自己的第一个java程序

    原文链接:https://blog.csdn.net/nextljp/article/details/77949597 IntelliJ IDEA目前公认的最好的java开发工具,不过一般的学校的教学还是使用eclipse来进行java的开发。所以老师一般只会教你如何用eclipse进行java的开发,在本篇文章你将学会IntelliJ IDEA的基本操作,并学…...

    2024/4/17 3:17:13
  3. 五年Java程序员终于完成了月入三万的目标,这是给我520最好礼物,辛苦了从前的自己

    一、前言我觉得像我这般年纪的(29岁),有相对扎实技术功底的(就不自谦了),对赚钱有着强烈欲望的程序员,应该定一个切实的小目标——五年内月入三万!之所以要定这个目标,最主要的原因是老婆的批评刺痛了我——一个身强力壮的年轻男子(脑子也还好使),不想方设法的多挣…...

    2024/4/23 15:21:45
  4. JVM面试题---进阶篇(一)

    一,垃圾回收,如何判断哪些对象当作垃圾需要被回收? 在内存中,要进行垃圾回收,首先我们先明确什么是垃圾?内存中不再使用的内存空间我们都称为垃圾。 如何判断该对象是否需要垃圾回收? 可达性分析算法也称根搜索路径算法:从GC Root对象为起点,向下开始搜索,如果一个对…...

    2024/4/23 15:21:48
  5. 小白的springMVC入门笔记(基础向)

    学完mybatis,就赶紧来学springMVC了,这是B站的学习视频(B站果然是一个学习网站QWQ)springMVC入门笔记 介绍springMVC代替之前学的sturts2框架缩写 M:model模型–>javaBean v:view视图–>jsp c:controller控制器–>servlet springMVC和Struts2的优劣 共同点:都…...

    2024/4/23 15:21:46
  6. java IO流_其他流_字节数组流与文件流对接_练习

    package IO流_其他流_字节数组流; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotF…...

    2024/4/23 15:21:43
  7. 计算机网络(BYSEE)第二章 物理层 学习笔记(0518)

    第二章 物理层 2.1 物理层的基本概念 物理层:在连接各种计算机的传输媒体上传输数据比特流 物理层的协议也常称为物理层规程 (procedure) 机械特性、电气特性、功能特性、过程特性 2.2 数据通信的基础知识 2.2.1 数据通信系统的模型 源系统、传输系统、目的系统 数据 (data) …...

    2024/4/23 15:21:48
  8. docker基本知识(一)

    docker简介docker是一个基于GO语言开发的,遵从Apache2.0协议的开源的应用容器引擎。 docker使得开发者将他的应用及依赖放到一个轻量级、可移植的容器中,然后发布到任何一个Linux机器上,或者可以实现虚拟化。 完全使用沙箱机制,相互之间不会有任何接口应用场景web应用的自动…...

    2024/4/23 15:21:42
  9. Window下配置Java与IntelliJ Idea

    环境配置步骤Java环境配置具体步骤官网下载java jdk安装 jdk 与 jre配置环境变量配置结果测试Java IDE——ItelliJ IDEA 2020.1.1配置官网下载安装包安装Idea并激活个性化设置目标环境:windows 10 pro 64位操作系统 Java SE版本:jdk-14.0.1 Java IDE:IntelliJ Idea 2020.1.1…...

    2024/4/23 15:21:40
  10. Apache Dubbo

    一、 软件架构的演进过程 1、单体架构架构说明: 所有的功能集中在1个项目内。 优点:架构简单,前期开发成本低、开发周期短,适合小型项目。缺点:1、项目不利于扩展、难以维护 2、技术栈受限:只能使用1种开发语言 3、系统性能扩展只能通过扩展集群节点,成本高2、垂直架构架…...

    2024/4/23 15:21:38
  11. JMeter监控服务器资源步骤(界面化)

    JMeter元件执行顺序: 1、配置元件例如:HTTP请求默认值例如:HTTP请求头管理例如:用户定义变量 2、前置处理器例如:用户参数 3、定时器例如:固定时间 4、提取器(sampler)例如:公共接口请求 5、后置处理器例如:正则提取器 6、断言例如:3种断言:size断言、响应断言、响应…...

    2024/4/23 15:21:40
  12. BP神经网络

    大白话讲解BP算法最近在看深度学习的东西,一开始看的吴恩达的UFLDL教程,有中文版就直接看了,后来发现有些地方总是不是很明确,又去看英文版,然后又找了些资料看,才发现,中文版的译者在翻译的时候会对省略的公式推导过程进行补充,但是补充的又是错的,难怪觉得有问题。反…...

    2024/4/23 15:21:37
  13. 出现这种错误 Failed to bind properties under ” to com.zaxxer.hikari.HikariDataSource:

    在做springBoot与mybatis整合的时候 在测试的时候出现一下错误java.lang.IllegalStateException: Failed to load ApplicationContextat org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate…...

    2024/4/23 15:21:35
  14. DNN语音增强实现

    获取干净语音及噪声语音数据,可以使用soundfile中的read函数;获取语音有些困难,因为语音数据庞大,因此需要调整获取语音数据的方式; 已知:(1)语音数据:包括speech,noise(训练数据、验证数据及测试数据未分类);(2)训练数据文本文档、验证数据文本文档、测试数据文…...

    2024/4/23 15:21:34
  15. 顺序表增删查改,翻转,合并

    顺序表的增,删,查,改,翻转,合并此文章用于记录顺序表的知识 此文章用于记录顺序表的知识 今天下午突发其想想知道自己还会不会顺序表,于是花了大概一个小时写了下面这段程序。欢迎交流讨论。 // 代码部分 // // gradation_link.c // test // // Created by echo on 20…...

    2024/4/17 3:18:01
  16. hdu4003 Find Metal Mineral(树形dp+分组背包思想)

    题目n(n<=1e4)个点的树,每条边有一个边权w(w<=1e4),通过其的代价为其权值你有k(k<=10)个机器人,所有机器人从给定的源点s(1<=s<=n)出发,你可以控制机器人的移动求机器人访问所有点时,其最小的边权代价总和,输出代价总和1<=N<=10000, 1<=S<=N,…...

    2024/4/17 3:18:07
  17. 关于二叉树和图

    1、树 关于树的基本介绍 二叉树 完全二叉树:优先左子树,且除最后一层以外的其他每一层都被完全填充 左子树位置=父节点*2+1 右子树位置=父节点*2+2 满二叉树:每一层都被完全填充完满二叉树:除叶子节点之外的每个结点都有两个孩子二叉搜索树,又叫二叉排序树 平衡二叉树:AV…...

    2024/4/16 14:10:34
  18. getchar()使用清缓冲区

    void Input() {char answer;do{printf("是否继续录入英雄的信息?(y/n)");answer = getchar();rewind(stdin);//加上清缓冲区} while (answer==y|| answer==Y); }...

    2024/4/17 3:17:37
  19. springboot配置Swagger2生成API接口文档

    一、Swagger2介绍前后端分离开发模式中,api文档是最好的沟通方式。Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。及时性 (接口变更后,能够及时准确地通知相关前后端开发人员)规范性 (并且保证接口的规范性,如接口的地址,请求方…...

    2024/4/15 8:03:26
  20. 算法复杂性_复杂网络与复杂系统学习笔记01

    算法复杂性是19964-1966年由索洛莫诺夫、科尔莫戈罗夫和柴廷分别独立提出的,粗略的说,算法复杂性就是产生特定的图形花纹(或符号序列)的最短程序的长度与图形花纹(或符号序列)本身的大小之比的极限。这里‘长度’和‘大小’均按二进制位数计,而‘程序’则是在普适的理论…...

    2024/4/20 10:02:05

最新文章

  1. ClickHouse高原理与实践

    ClickHouse高原理与实践 1 ClickHouse的特性1.1. OLAP1.2. 列式存储1.3. 表引擎1.4. 向量化执行1.5. 分区1.6. 副本与分片1.7 其他特性 2. ClickHouse模块设计2.1 Parser分析器与Interpreter解释器2.2 Storage2.3 Column与Field2.4 DataType2.5 Block2.6 Cluster与Replication …...

    2024/5/1 11:05:38
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 人工智能产业应用--具身智能

    五、下一个浪潮 (一) 跳出缸中脑——虚实结合 在探索人工智能的边界时&#xff0c;“跳出缸中脑——虚实结合”这一概念提出了一个引人深思的视角&#xff0c;尤其是在具身智能的领域。具身智能是一种思想&#xff0c;强调智能体通过与其环境的直接物理互动来实现智能行为。然…...

    2024/4/30 0:58:30
  4. 基于单片机和Wi-Fi 技术的家电远程控制系统设计

    摘要:根据家用电器的智能开关控制需求,提出基于单片机和Wi-Fi 技术的家电远程控制系统的设计。从硬件与软件两部分对单片机电路、Wi-Fi 电路、继电器电路,及其程序进行设计。设计的家电远程控制系统,经Tlink 物联网平台模拟测试,信号反应无误,为进一步实际应用提供了基础…...

    2024/4/30 7:45:21
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/29 23:16:47
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/30 18:14:14
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/30 18:21:48
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/30 9:43:22
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57