UI自动刷新大法:DataBinding数据绑定

之前我们讲了DataBinding在Activity、Fragment、RecyclerView中的基础使用,而那些常规使用方法里,每当绑定的变量发生数据变化时,都需要ViewDataBinding重新设值才会刷新对应UI。而DataBinding通过内部实现的观察者模式来进行自动刷新UI,这块内容是DataBinding的重要部分。在观察者模式的角度下,DataBinding库,允许我们使用对象、字段,或者集合来进行观察,当其中的一个可观察者数据对象绑定到了视图当中,并且数据对象的属性发生更改变化的时候,视图将会自动更新。而根据绑定的方式不同,又可分为 单向绑定双向绑定

单向绑定,实现数据变化自动驱动UI刷新,方式有三种:BaseObservable,ObservableField、ObservableCollection。在此之前,先让我们来了解下事件绑定。

前言 事件绑定

为了更好的了解单向绑定和后续的双向绑定,我们先来看下DataBinding中事件绑定的方式。严格来说,事件绑定也是一种变量绑定,只不过设置的绑定不再是单纯的变量,还是回调接口,事件绑定可设置的回调事件有以下:

android:onClick
android:onLongClick
android:onTextChanged
android:afterTextChanged
...

对应使用步骤也较为简单:

第一步 声明内部类

在要使用的activity类里新建一个内部类来声明对应的回调方法,这里我们接着用上篇文章中的工程来继续修改。我们在MainActivity中新建一个内部类,里面声明onClick()和afterTextChanged()事件:

public class MainActivity extends AppCompatActivity {UserInfo userInfo;DemoBinding viewDataBinding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);userInfo = new UserInfo("亚历山大", 66);viewDataBinding.setUserInfoExample(userInfo);viewDataBinding.setUserEventListener(new EventListener());}public class EventListener{public void changedUserName(){userInfo.setName("鸭梨山大二世");viewDataBinding.setUserInfoExample(userInfo);}public void changedUserInfo(){userInfo.setName("鸭力山大三世");userInfo.setAge(81);viewDataBinding.setUserInfoExample(userInfo);}}
}

第二步 修改布局标签内容

同时还要在相应布局文件中的< data>标签里声明此内部类路径,在对应设置此点击事件回调的控件里通过内嵌表达式 @{} 来设置引用。

<?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><import type="com.example.dbjavatest.MainActivity.EventListener"/><import type="com.example.dbjavatest.bean.UserInfo"/><variablename="UserInfoExample"type="UserInfo" /><variablename="UserEventListener"type="EventListener" /></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/tv_user_first"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="@{()->UserEventListener.changedUserName()}"android:text="@{UserInfoExample.name,default=defaultValue}"app:layout_constraintTop_toTopOf="parent"app:layout_constraintStart_toStartOf="parent"/><TextViewandroid:id="@+id/tv_user_second"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{String.valueOf(UserInfoExample.age),default=defaultValue}"app:layout_constraintTop_toBottomOf="@+id/tv_user_first"app:layout_constraintStart_toStartOf="parent"/><Buttonandroid:id="@+id/btn_change"android:layout_width="match_parent"android:layout_height="wrap_content"app:layout_constraintTop_toBottomOf="@+id/tv_user_second"app:layout_constraintStart_toStartOf="parent"android:text="改变属性"android:onClick="@{()->UserEventListener.changedUserInfo()}"/></androidx.constraintlayout.widget.ConstraintLayout>
</layout>

在这布局文件中,android:onClick="@{()->UserEventListener.changedUserName()}"属性含义即为点击事件响应方法为指定的UserEventListener中的changedUserName(),运行后,可查看效果如下:

DataBinding点击事件.gif

单向数据绑定之Base Observable

众所周知,一个单纯的ViewModel类被更新后,并不会让UI自动更新。Observable存在的目的就是为了数据变更后UI会自动刷新。

在此方面,Observable提供了两个方法:

· notifyChange()
· notifyPropertyChanged()

方法一notifyChange()会刷新所有的UI。

方法二notifyPropertyChanged()只会刷新属于它的UI,需要绑定属性(通过注解 @Bindable来绑定)。

使用方式也较为简单:

第一步 修改实体bean类

使实体bean类继承自BaseObservable:

public class UserInfo extends BaseObservable {public UserInfo(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;notifyPropertyChanged(BR.name);}public void setNameAndAge(String name,int age){this.name = name;this.age = age;notifyChange();}@Bindablepublic int getAge() {return age;}public void setAge(int age) {this.age = age;}@Bindablepublic String name; //public属性成员可直接在成员变量上方加上@Bindableprivate int age; //private属性成员需要在其get方法上添加@Bindable
}

第二步、修改对应Activity

为了凸显出区别,我们继续沿用上面点击事件中例子的布局,不做修改,但是Activity中代码要修改:

public class MainActivity extends AppCompatActivity {UserInfo userInfo;ActivityMainBinding viewDataBinding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);userInfo = new UserInfo("亚历山大", 66);viewDataBinding.setUserInfoExample(userInfo);viewDataBinding.setUserEventListener(new EventListener());}public class EventListener{public void changedUserName(){userInfo.setName("鸭梨山大二世");userInfo.setAge(999);//无效}public void changedUserInfo(){userInfo.setNameAndAge("鸭力山大X世",new Random().nextInt(100));}}
}

可以看到,相比于普通的点击事件代码中明显少了viewDataBinding.setUserInfoExample…等操作,可能一两个点击事件看不出明显差别,但事件一多,你会发现Activity的代码会省略很多,非常利于代码解耦和整洁性。这也不影响相应效果,运行效果如下:

DataBinding中的Observable点击事件.gif

可见,在点击用户名时,userInfo.setAge(999)执行无效的,因为在原实体bean类中,只设置了改变name属性(notifyPropertyChanged(BR.name)):

image.gif
所以在点击name属性的时候,只有名字在变化,而点击事件里setNameAndAge()中因为声明了notifyChange();改变所有元素,因此可看到点击按钮时,全局属性跟着改变了(name属性一致固定写死,所以你可能觉得名字没变化)。

二、单项数据绑定之ObservableField

有的时候相应工程里,实体Bean类需要继承其他类,这样就无法使用Observable了。这时有另外一个方案,即ObservableField。PS:ObservableField不需要进行notify操作。

在ObservableField中,官方提供了对基本数据类型的封装,如ObservableInt、ObservableLong、ObservableFloat、ObservableDouble ObservableShort、ObservableBoolean、ObservableByte、ObservableChar以及 ObservableParcelable 。当然也可通过泛型来申明其他类型,可以说这是官方对Observable中字段的注解和刷新等操作等封装。

其使用方式与Observable还是有点区别的:

第一步 修改实体bean类

public class UserInfo{public final ObservableField<String> name;public final ObservableField<Integer> age;public ObservableField<String> getName() {return name;}public ObservableField<Integer> getAge() {return age;}public UserInfo(String name,Integer age){this.name=new ObservableField<>(name);this.age= new ObservableField<Integer>(age);}
}

可见Bean文件在这里取消了继承,对变量进行了public final修饰,重写对应的get()(final修饰的变量无法写set())。其set()属性的方式则有些许不一样。

第二步 修改对应逻辑

在对应需要进行set逻辑的地方,可以通过ObservableField提供的get、set方法,去拿到值和设置值来达到更新UI效果。如下:

public class MainActivity extends AppCompatActivity {UserInfo userInfo;ActivityMainBinding viewDataBinding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);userInfo = new UserInfo("亚历山大", 66);viewDataBinding.setUserInfoExample(userInfo);viewDataBinding.setUserEventListener(new EventListener());}public class EventListener{public void changedUserName(){userInfo.getName().set("鸭梨山大二世");}public void changedUserInfo(){userInfo.getName().set("鸭梨山大一世");userInfo.getAge().set(new Random().nextInt(101));}}
}

对应的效果为:

DataBinding-Field点击事件.gif

三、单项数据绑定之ObservableCollection

ObservableCollection中最常用的是ObservableList 和 ObservableMap,即dataBinding 提供的包装类用于替代原生的 List 和 Map。其使用方式与前两者差别也不大。

第一步 修改Collection布局

这里我们不再使用实体bean类,而是dataBinding 包装的ObservableMap和ObservableList元素,因此需要修改< data>标签。如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"><data><import type="androidx.databinding.ObservableMap"/><import type="androidx.databinding.ObservableList"/><!--注意这里,只能用 "&lt;"和 "&gt;"--><variablename="list"type="ObservableList&lt;String&gt;"/><variablename="map"type="ObservableMap&lt;String,Integer&gt;"/><variablename="sing"type="String"/><variablename="num"type="int"/></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/tv_user_first"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{list[num],default=syt}"app:layout_constraintTop_toTopOf="parent"app:layout_constraintStart_toStartOf="parent"/><TextViewandroid:id="@+id/tv_user_second"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{String.valueOf(map[sing]),default=sys}"app:layout_constraintTop_toBottomOf="@+id/tv_user_first"app:layout_constraintStart_toStartOf="parent"/><Buttonandroid:id="@+id/btn_change"android:layout_width="match_parent"android:layout_height="wrap_content"app:layout_constraintTop_toBottomOf="@+id/tv_user_second"app:layout_constraintStart_toStartOf="parent"android:text="改变属性"android:onClick="onButtonClick"/></androidx.constraintlayout.widget.ConstraintLayout>
</layout>

这里的ObservableMap和ObservableList归属的databinding在androidX包里,如果你的工程还没有适配安卓X,最好请尽快适配。最后一个Button里的android:onClick="onButtonClick"可能会让你感到疑惑,但其实这也是dataBinding里的控件的点击事件写法之一。

第二步 修改Activity中对应逻辑

其Activity中代码就如下:

public class MainActivity extends AppCompatActivity{ActivityMainBinding viewDataBinding;private ObservableMap<String, Integer> map;ObservableArrayList<String> obList;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);map = new ObservableArrayMap<>();map.put("test_num",1 );map.put("test_biger_num", 100);viewDataBinding.setMap(map);obList = new ObservableArrayList<>();obList.add("ObservableArrayList");obList.add("observablelist");obList.add("observablelist more");viewDataBinding.setList(obList);viewDataBinding.setNum(0);viewDataBinding.setSing("test_biger_num");}public void onButtonClick(View v) {map.put("test_biger_num",new Random().nextInt(99));}}

对应效果如下:

DataBinding_ObservableCollection点击事件.gif

当然,设置点击事件还有一种方法引用,直接用 :: 即可,
如: android:onClick=“@{listener::onClick}” 就是方法引用绑定!

四、双向数据绑定

双向绑定含义就是 在数据更新时使得View也能更新,而View更新的时候也同时更改数据

此法不适合所有的应用场景,但也有相应的应用场景,比如用户注册登录场景,在输入账号和密码同时,UI刷新同时数据也更新,这里就适合双向绑定。可以说,双向绑定时安卓MVVM架构的基础。
这次简单实例我们用ObservableField方式,先写一个bean实体类:

public class DataBean {public final ObservableField<String> dataInfo;public DataBean(ObservableField<String> dataInfo) {this.dataInfo = dataInfo;}public ObservableField<String> getDataInfo() {return dataInfo;}
}

对应也要修改布局文件和引入,如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"><data><import type="com.example.dbjavatest.bean.DataBean"/><variablename="dataInfoBean"type="DataBean" /></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/tv_data"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="26sp"android:textColor="@color/purple_200"android:text="@{dataInfoBean.dataInfo}"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"android:layout_marginLeft="50dp"/><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:hint="请输入数据"android:text="@={dataInfoBean.dataInfo}"app:layout_constraintTop_toBottomOf="@+id/tv_data"android:textSize="25sp"android:layout_marginTop="30dp"android:paddingLeft="20dp"/></androidx.constraintlayout.widget.ConstraintLayout>
</layout>

这里要注意,在EditText中更新数据时会同步到上面的TextView,绑定方式跟单向绑定方式相比,要在内嵌表达式中多用一个“=”,即android:text=“@={dataInfoBean.dataInfo}”。

对应Activity中代码如下:

public class MainActivity extends AppCompatActivity{ActivityMainBinding viewDataBinding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);DataBean dataBean = new DataBean(new ObservableField<String>(""));viewDataBinding.setDataInfoBean(dataBean);}
}

效果也能猜到:

DataBinding双向绑定.gif

五、List Set Map等数据结构

除了ObservableCollection,DataBinding也支持原生Java数据结构(数组、List、Set和Map)在布局文件中使用,且在布局文件中都可以通过list[index]的形式来获取元素。

官方为了和< variable>标签元素区分开,在声明具有多个泛型的数据类型时,需要使用"& lt;"和 " >"用以区分。如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><data><import type="java.util.List" /><import type="java.util.Set" /><import type="java.util.Map" /><variablename="array"type="String[]" /><variablename="list"type="List&lt;String&gt;" /><variablename="map"type="Map&lt;String, String&gt;" /><variablename="set"type="Set&lt;String&gt;" /><variablename="num"type="int" /><variablename="sing"type="String" /></data><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><TextView···android:text="@{array[1]}" /><TextView···android:text="@{list[num]}" /><TextView···android:text="@{map[sing]}" /><TextView···android:text='@{map["test"]}' /></LinearLayout>
</layout>

六、使用相应类方法

在DataBinding中,使用相应类方法,可现在< data>标签中导入该类不需要写<vari…>标签,然后在布局中像对待一般方法来调用就行。

例如,先写个没啥用的静态类:

public class UIUtils {public static String showTheDemo(String str) {return str.toString();}}

在< data>中引入该类:

<import type="com.example.dbjavatest.UIUtils" />

然后在对应控件里调用:

<TextViewandroid:id="@+id/tv_data"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="26sp"android:textColor="@color/purple_200"android:text="@{UIUtils.showTheDemo(dataInfoBean.dataInfo)}"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"android:layout_marginLeft="50dp"/>

PS : DataBinding中布局里的控件通过嵌入表达式不仅可以引用对应方法,也可以使用三元运算符等运算符。

七、include和viewStub

DataBinding也支持include的布局文件,一样通过dataBinding来进行数据绑定,一样需要使用< layout>标签和声明需要使用的变量,然后在主布局中将对应的变量传递给include布局,使两个布局共享的数据变量相同。

例如:view_insert.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"><data><import type="com.example.dbjavatest.bean.DataBean"/><variablename="dataInfoBean"type="DataBean" /></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:hint="请输入数据"android:text="@={dataInfoBean.dataInfo}"app:layout_constraintTop_toTopOf="parent"app:layout_constraintStart_toStartOf="parent"android:textSize="25sp"android:layout_marginTop="30dp"android:paddingLeft="20dp"/></androidx.constraintlayout.widget.ConstraintLayout>
</layout>

对应主布局则直接include,同时通过bind:变量名来将同一变量传过去。你可能发现这里会报错,在布局头文件声明xmlns:bind=“http://schemas.android.com/apk/res-auto” 即可。对应布局文件为:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:bind="http://schemas.android.com/apk/res-auto"><data><import type="com.example.dbjavatest.bean.DataBean"/><variablename="dataInfoBean"type="DataBean" /></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/tv_data"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="26sp"android:textColor="@color/purple_200"android:text="@{dataInfoBean.dataInfo}"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"android:layout_marginLeft="50dp"/><includelayout="@layout/view_insert"app:layout_constraintTop_toBottomOf="@+id/tv_data"bind:dataInfoBean = "@{dataInfoBean}"/></androidx.constraintlayout.widget.ConstraintLayout>
</layout>

ViewStub绑定变量和将变量传递给ViewStub的方式与此一致。例如:

<ViewStubandroid:id="@+id/view_stub"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout="@layout/view_insert"bind:dataInfoBean="@{dataInfoBean}" />

当然,ViewStub 文件一样要使用 layout 等标签进行布局。相应的在Activity中也是通过ViewBinding获取对象实例:

View viewStub = viewDataBinding.viewStub.getViewStub().inflate();

通过此实例,可以控制viewStub的可见性。如果在xml中,没用使用bind:dataInfoBean=“@{dataInfoBean}”,但又想对ViewStub进行数据绑定。则可以在ViewStub 设置 setOnInflateListener回调函数时进行数据绑定,如下:

viewDataBinding.viewStub.setOnInflateListener(new ViewStub.OnInflateListener() {@Overridepublic void onInflate(ViewStub stub, View inflated) {ViewDataBinding viewStubBinding = DataBindingUtil.bind(inflated);viewStubBinding.setDataInfoBean(dataBean);}
});

对DataBinding的数据绑定就介绍到这里了,如果后续发现有遗漏的要点,会即使补充。另外,如果看这篇文字有点吃力,说明你对DataBinding的基础操作还不熟悉,请翻阅我的上一片文章。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/678717.shtml

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

相关文章

go消息队列RabbitMQ - 订阅模式-direct

1.发布订阅 在Fanout模式中&#xff0c;一条消息&#xff0c;会被所有订阅的队列都消费。但是&#xff0c;在某些场景下&#xff0c;我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。 在Direct模型下&#xff1a; 队列与交换机的绑定&#xff0c;不能…

第 384 场 LeetCode 周赛题解

A 修改矩阵 模拟 class Solution { public:vector<vector<int>> modifiedMatrix(vector<vector<int>> &matrix) {int m matrix.size(), n matrix[0].size();vector<int> mx(n, INT32_MIN);for (int i 0; i < m; i)for (int j 0; j &l…

Java微服务学习Day1

文章目录 认识微服务服务拆分及远程调用服务拆分服务远程调用提供者与消费者 Eureka注册中心介绍构建EurekaServer注册user-serviceorder-service完成服务拉取 Ribbon负载均衡介绍原理策略饥饿加载 Nacos注册中心介绍配置分级存储负载均衡环境隔离nacos注册中心原理 认识微服务…

Python : 使用python实现学生管理系统的功能,详细注释

一、学生管理系统 学生描述&#xff1a;姓名、年龄、成绩 学生管理系统功能&#xff1a;添加学生信息、删除学生信息、根据姓名修改学生信息、根据姓名查询学生信息、显示所有学生信息、退出系统 二、代码说明 1. 将每一个学生的信息放一个元组中&#xff0c;再把元组添加到列表…

单片机基础入门:简单介绍51单片机的工作原理

在电子技术领域&#xff0c;单片机是实现智能化控制不可或缺的关键元件。它们集成了许多功能于一身&#xff0c;成为了各种电子系统的心脏。为了更好地理解单片机如何工作&#xff0c;本文将重点介绍51单片机的基本组成和工作原理。 51单片机是一种广泛使用的微控制器&#xf…

【UE 求职】学了虚幻引擎可以应聘哪些岗位?

目录 1 领域1.1 游戏开发领域1.2 影视和动画制作1.3 建筑和工程可视化1.4 模拟和训练1.5 其他领域 2 如何做好一份简历1. 明确简历目标2. 突出UE5相关技能3. 展示相关项目经验4. 教育背景5. 专业经验6. 软技能7. 证书和奖项8. 定制化和校对 &#x1f64b;‍♂️ 作者&#xff1…

使用PHPStudy搭建本地web网站并实现任意浏览器公网访问

文章目录 [toc]使用工具1. 本地搭建web网站1.1 下载phpstudy后解压并安装1.2 打开默认站点&#xff0c;测试1.3 下载静态演示站点1.4 打开站点根目录1.5 复制演示站点到站网根目录1.6 在浏览器中&#xff0c;查看演示效果。 2. 将本地web网站发布到公网2.1 安装cpolar内网穿透2…

springcloud分布式架构网上商城源码和论文

首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计。本项…

Unity Meta Quest MR 开发(四):使用 Scene API 和 Depth API 实现深度识别和环境遮挡

文章目录 &#x1f4d5;教程说明&#x1f4d5;Scene API 实现遮挡&#x1f4d5;Scene API 实现遮挡的缺点&#x1f4d5;Depth API 实现遮挡⭐导入 Depth API⭐修改环境配置⭐添加 EnvironmentDepthOcclusion 预制体⭐给物体替换遮挡 Shader⭐取消现实手部的遮挡效果 此教程相关…

Peter算法小课堂—背包问题

我们已经学过好久好久的动态规划了&#xff0c;动态规划_Peter Pan was right的博客-CSDN博客 那么&#xff0c;我用一张图片来概括一下背包问题。 大家有可能比较疑惑&#xff0c;优化决策怎么优化呢&#xff1f;答案是&#xff0c;滚动数组&#xff0c;一个神秘而简单的东西…

点云标注工具

目录 3d手势识别 c 3d关键点&#xff0c;Bounding Box Labels Rectangle Labels KITTI 3D Ground Truth Annotator c标注工具 3d手势识别 GitHub - 99xtaewoo/Automated-Hand-3D-pose-annotation-Tool: Automated Hand 3D pose annotation Tool c 3d关键点&#xff0c;Bou…

bcdedit /store 填什么,Windows11的BCD文件在哪里?

Windows11为EFI引导&#xff0c;bcd文件在 EFI分区的 \EFI\Microsoft\Boot\BCD 可以选择挂载EFI分区&#xff0c;或者使用如下方式&#xff0c;该路径可充当盘符使用。 例 bcdedit /store Z:\EFI\Microsoft\Boot\BCD /enum /v

【LeetCode每日一题】二维前缀和基本概念与案例

二维前缀和 根据某个块块 的 左上角坐标&#xff0c;和右下角坐标 求出 块块的累加和。 304. 二维区域和检索 - 矩阵不可变 /*** param {number[][]} matrix*/ var NumMatrix function(matrix) {let row matrix.length;let col matrix[0].length;// 初始化一个二维数组&am…

项目02《游戏-13-开发》Unity3D

基于 项目02《游戏-12-开发》Unity3D &#xff0c; 任务 &#xff1a;宠物系统 及 人物头像血条 首先在主面板MainPanel预制体中新建一个Panel&#xff0c; 命名为PlayerInfo 新建Image&#xff0c;作为头像 新建Slider&#xff0c;作为血条 对Panel组件添加一个水…

PE 特征码定位修改程序清单 uiAccess

requestedExecutionLevel level"asInvoker" uiAccess"false" 可以修改这一行来启用禁用原程序的盾牌图标&#xff0c;似乎作用不大。以前没事写的一个小玩意&#xff0c;记录一下。 等同于这里的设置&#xff1a; 截图 代码如下&#xff1a; #include …

谷粒商城【成神路】-【7】——库存系统

目录 &#x1f9c8;1.仓库维护 &#x1f35f;&#x1f35f;1.1配置网关陆游规则 &#x1f35f;&#x1f35f;1.2修改模糊查询 &#x1f95e;2.仓库库存 &#x1f37f;3.采购需需求 &#x1f35f;&#x1f35f;3.1采购的模糊检索 &#x1f35f;&#x1f35f;3.2合并…

system V——进程间通信

上一篇博客中我介绍了system V进程间通信中的内存共享&#xff0c;但是其中还有两 种通信方式&#xff1a;消息队列、和信号量&#xff0c;接下来我将简单介绍一下&#xff0c;消息队列和 信号量以及操作系统是如何看待system V进程间通信的。1. 消息队列 a. 大致介绍 消息队…

4核8G服务器配置性能怎么样?12M带宽配置服务器能干什么?

腾讯云轻量4核8G12M轻量应用服务器支持多少人同时在线&#xff1f;通用型-4核8G-180G-2000G&#xff0c;2000GB月流量&#xff0c;系统盘为180GB SSD盘&#xff0c;12M公网带宽&#xff0c;下载速度峰值为1536KB/s&#xff0c;即1.5M/秒&#xff0c;假设网站内页平均大小为60KB…

CVE-2012-1823 漏洞复现

CVE-2012-1823 PHP SAPI 与运行模式 首先&#xff0c;介绍一下PHP的运行模式。 下载PHP源码&#xff0c;可以看到其中有个目录叫sapi。sapi在PHP中的作用&#xff0c;类似于一个消息的“传递者”&#xff0c;比如在《Fastcgi协议分析 && PHP-FPM未授权访问漏洞 &…

中年低端中产程序员从西安出发到海南三亚低成本吃喝万里行:西安-南宁-湛江-雷州-徐闻-博鳌-陵水-三亚-重庆-西安

文章大纲 旅途规划来回行程的确定南宁 - 北海 - 湛江轮渡成为了最终最大的不确定性&#xff01;感谢神州租车气温与游玩地点总体花费 游玩过程出发时间&#xff1a;Day1-1月25日星期四&#xff0c;西安飞南宁路途中&#xff1a;Day2-1月26日星期五&#xff0c;南宁-湛江-住雷州…