首页 文章 精选 留言 我的

精选列表

搜索[会话联动],共7799篇文章
优秀的个人博客,低调大师

Vue 3 中 watch 和 watchEffect 的刷新时机:从一次表单联动失效说起

有一个在 Vue 3 项目里很常见的场景:父组件传进来一个 props.id,子组件需要根据这个 id 去请求详情数据,同时在本地维护一份可编辑的表单副本。某次需求里,表单里有个“数量”输入框,修改数量后要自动计算总价并且把结果同步回一个隐藏字段。代码大概是这样写的:在 watchEffect 里读取 form.count 和 form.price,算出 form.total。结果发现,当用户快速连续修改数量时,总价偶尔会落后一拍,甚至出现用旧值计算的情况。排查后发现,问题不在于响应式数据本身,而是对 watch 和 watchEffect 的刷新时机理解不够。Vue 3 的侦听器默认在组件更新前触发(pre),而 watchEffect 的依赖收集是自动的,当回调里既有同步计算又有 DOM 读取时,刷新顺序会直接影响结果。这篇文章从这次排查过程出发,梳理 watch 与 watchEffect 的默认刷新时机、flush 选项的实际行为、onCleanup 的正确用法,以及什么场景该用 watch、什么场景该用 watchEffect。

优秀的个人博客,低调大师

阿里云发布边缘节点服务2.0,建立“融合、开放、联动”的边缘计算新形态

“5G时代,边缘计算将发挥更大价值。”阿里云边缘计算技术负责人杨敬宇表示,边缘计算作为5G时代的一项关键技术,未来将成为不可或缺的基础设施之一。那么云的能力是如何深入每个计算场景的?用户如何享受技术红利?阿里云ENS从1.0到2.0时代又完成了怎样的升级蜕变?在刚刚落幕的阿里云峰会北京站-边缘计算专场中,杨敬宇对以上问题做了解答。 一场计算体系架构的巨大革命,需要更多行业玩家进入 在5G和边缘计算到来之后,云、端二体协同向着云边端三体协同去发展,毋庸置疑,这是未来架构的新形态,杨敬宇将整个过程称之为一场计算体系架构的巨大革命。低延迟、大带宽、自定义、高效能、高安全成为了行业颇为关注的几大趋势。 据Gartner预测,2021年将有40%的大型企业在项目中纳入边缘计算原则。而到2022年,边缘计算将成为所有数字业务的必要需求。 而谈到行业,

优秀的个人博客,低调大师

一文彻底搞懂 Design 设计的 CoordinatorLayout 和 AppbarLayout 联动,让 Design 设计更简单~

一、写在前面 其实博主在之前已经对 Design 包的各个控件都做了博文说明,无奈个人觉得理解不够深入,所以有了这篇更加深入的介绍,希望各位看官拍砖~ 二、从是什么开始 1、首先我们得知道 CoordinatorLayout 是什么玩意儿,到底有什么用,我们不妨看看官方文档的描述: CoordinatorLayout 是一个 “加强版” FrameLayout, 它主要有两个用途: 用作应用的顶层布局管理器,也就是作为用户界面中所有 UI 控件的容器; 用作相互之间具有特定交互行为的 UI 控件的容器,通过为 CoordinatorLayout 的子 View 指定 Behavior, 就可以实现它们之间的交互行为。 Behavior 可以用来实现一系列的交互行为和布局变化,比如说侧滑菜单、可滑动删除的 UI 元素,以及跟随着其他 UI 控件移动的按钮等。 其实总结出来就是 CoordinatorLayout 是一个布局管理器,相当于一个增强版的 FrameLayout,但是它神奇在于可以实现它的子 View 之间的交互行为。 2、交互行为? 先看个简单的效果图 可能大家看到这,就自然能想到观察者模式,或者我前面写的Rx模式: 这可能是最好的RxJava 2.x 教程(完结版) 我们的 Button 就是一个被观察者,TextView 作为一个观察者,当 Button 移动的时候通知 TextView, TextView 就跟着移动。看看其布局: <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout 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" android:id="@+id/activity_coordinator" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.nanchen.coordinatorlayoutdemo.CoordinatorActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="观察者" app:layout_behavior=".FollowBehavior"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="被观察者" android:layout_gravity="center" android:id="@+id/btn"/> </android.support.design.widget.CoordinatorLayout> 很简单,一个 TextView, 一个 Button, 外层用 CoordinatorLayout, 然后给我们的 TextView 加一个自定义的 Behavior 文件,内容如下: package com.nanchen.coordinatorlayoutdemo; import android.content.Context; import android.support.design.widget.CoordinatorLayout; import android.util.AttributeSet; import android.view.View; import android.widget.Button; import android.widget.TextView; /** * * 自定义 CoordinatorLayout 的 Behavior, 泛型为观察者 View ( 要跟着别人动的那个 ) * * 必须重写两个方法,layoutDependOn和onDependentViewChanged * * @author nanchen * @fileName CoordinatorLayoutDemo * @packageName com.nanchen.coordinatorlayoutdemo * @date 2016/12/13 10:13 */ public class FollowBehavior extends CoordinatorLayout.Behavior<TextView>{ /** * 构造方法 */ public FollowBehavior(Context context, AttributeSet attrs) { super(context, attrs); } /** * 判断child的布局是否依赖 dependency * * 根据逻辑来判断返回值,返回 false 表示不依赖,返回 true 表示依赖 * * 在一个交互行为中,Dependent View 的变化决定了另一个相关 View 的行为。 * 在这个例子中, Button 就是 Dependent View,因为 TextView 跟随着它。 * 实际上 Dependent View 就相当于我们前面介绍的被观察者 * */ @Override public boolean layoutDependsOn(CoordinatorLayout parent, TextView child, View dependency) { return dependency instanceof Button; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, TextView child, View dependency) { child.setX(dependency.getX()); child.setY(dependency.getY() + 100); return true; } } 重点看看其中重写的两个方法 layoutDependsOn() 和 onDependentViewChanged() 。在介绍这两个方法的作用前,我们先来介绍一下 Dependent View。在一个交互行为中,Dependent View 的变化决定了另一个相关 View 的行为。在这个例子中, Button 就是 Dependent View, 因为 TextView 跟随着它。实际上 Dependent View 就相当于我们前面介绍的被观察者。 知道了这个概念,让我们看看重写的两个方法的作用: layoutDependsOn():这个方法在对界面进行布局时至少会调用一次,用来确定本次交互行为中的 Dependent View,在上面的代码中,当 Dependency 是Button 类的实例时返回 true,就可以让系统知道布局文件中的 Button 就是本次交互行为中的 Dependent View。 onDependentViewChanged():当 Dependent View 发生变化时,这个方法会被调用,参数中的child相当于本次交互行为中的观察者,观察者可以在这个方法中对被观察者的变化做出响应,从而完成一次交互行为。 所以我们现在可以开始写Activity中的代码: findViewById(R.id.btn).setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { if (motionEvent.getAction() == MotionEvent.ACTION_MOVE){ view.setX(motionEvent.getRawX()-view.getWidth()/2); view.setY(motionEvent.getRawY()-view.getHeight()/2); } return true; } }); 这样一来,我们就完成了为 TextView 和Button 设置跟随移动这个交互行为。很简单有木有,其实为 CoordinatorLayout 的子 View 设置交互行为只需三步: 自定义一个继承自 Behavior 类的交互行为类; 把观察者的 layout_behavior 属性设置为自定义行为类的类名; 重写 Behavior 类的相关方法来实现我们想要的交互行为。 值得注意的是,有些时候,并不需要我们自己来定义一个 Behavior 类,因为系统为我们预定义了不少 Behavior 类。在接下来的篇章中,我们会做出进一步的介绍。 3、更进一步 现在我们已经知道了怎么通过给 CoordinatorLayout 的子 View 设置 Behavior 来实现交互行为。现在,让我们更进一步地挖掘下 CoordinatorLayout, 深入了解一下隐藏在表象背后的神秘细节。 实际上, CoordinatorLayout 本身并没有做过多工作,实现交互行为的主要幕后推手是 CoordinatorLayout 的内部类—— Behavior。通过为 CoordinatorLayout 的**直接子 View **绑定一个 Behavior ,这个 Behavior 就会拦截发生在这个 View 上的 Touch 事件、嵌套滚动等。不仅如此,Behavior 还能拦截对与它绑定的 View 的测量及布局。关于嵌套滚动,我们会在后续文章中进行详细介绍。下面我们来深入了解一下 Behavior 是如何做到这一切的。 4、深入理解 Behavior 拦截 Touch 事件 当我们为一个 CoordinatorLayout 的直接子 View 设置了 Behavior 时,这个 Behavior 就能拦截发生在这个 View 上的 Touch 事件,那么它是如何做到的呢?实际上, CoordinatorLayout 重写了 onInterceptTouchEvent() 方法,并在其中给 Behavior 开了个后门,让它能够先于 View 本身处理 Touch 事件。具体来说, CoordinatorLayout 的 onInterceptTouchEvent() 方法中会遍历所有直接子 View ,对于绑定了 Behavior 的直接子 View 调用 Behavior 的 onInterceptTouchEvent() 方法,若这个方法返回 true, 那么后续本该由相应子 View 处理的 Touch 事件都会交由 Behavior 处理,而 View 本身表示懵逼,完全不知道发生了什么。 拦截测量及布局 了解了 Behavior 是怎养拦截 Touch 事件的,想必大家已经猜出来了它拦截测量及布局事件的方式 —— CoordinatorLayout 重写了测量及布局相关的方法并为 Behavior 开了个后门。没错,真相就是如此。 CoordinatorLayout 在 onMeasure() 方法中,会遍历所有直接子 View ,若该子 View 绑定了一个 Behavior ,就会调用相应 Behavior 的 onMeasureChild() 方法,若此方法返回 true,那么 CoordinatorLayout 对该子 View 的测量就不会进行。这样一来, Behavior 就成功接管了对 View 的测量。 同样,CoordinatorLayout 在 onLayout() 方法中也做了与 onMeasure() 方法中相似的事,让 Behavior 能够接管对相关子 View 的布局。 View 的依赖关系的确定 现在,我们在探究一下交互行为中的两个 View 之间的依赖关系是怎么确定的。我们称 child 为交互行为中根据另一个 View 的变化做出响应的那个个体,而 Dependent View 为child所依赖的 View。实际上,确立 child 和 Dependent View 的依赖关系有两种方式: 显式依赖:为 child 绑定一个 Behavior,并在 Behavior 类的 layoutDependsOn() 方法中做手脚。即当传入的 dependency 为 Dependent View 时返回 true,这样就建立了 child 和 Dependent View 之间的依赖关系。 隐式依赖:通过我们最开始提到的锚(anchor)来确立。具体做法可以这样:在 XML 布局文件中,把 child 的 layout_anchor 属性设为 Dependent View 的id,然后 child 的 layout_anchorGravity 属性用来描述为它想对 Dependent View 的变化做出什么样的响应。关于这个我们会在后续篇章给出具体示例。 无论是隐式依赖还是显式依赖,在 Dependent View 发生变化时,相应 Behavior 类的 onDependentViewChanged() 方法都会被调用,在这个方法中,我们可以让 child 做出改变以响应 Dependent View 的变化。 三、玩转AppBarLayout 实际上我们在应用中有 CoordinatorLayout 的地方通常都会有 AppBarLayout 的联用,作为同样的出自 Design 包的库,我们看看官方文档怎么说: AppBarLayout 是一个垂直的 LinearLayout,实现了 Material Design 中 App bar 的 Scrolling Gestures 特性。AppBarLayout 的子 View 应该声明想要具有的“滚动行为”,这可以通过 layout_scrollFlags 属性或是 setScrollFlags() 方法来指定。 AppBarLayout 只有作为 CoordinatorLayout 的直接子 View 时才能正常工作,为了让 AppBarLayout 能够知道何时滚动其子 View,我们还应该在 CoordinatorLayout 布局中提供一个可滚动 View,我们称之为 Scrolling View。 Scrolling View 和 AppBarLayout 之间的关联,通过将 Scrolling View 的 Behavior 设为 AppBarLayout.ScrollingViewBehavior 来建立。 1、一般怎么用?AppBar 是 Design 的一个概念,其实我们也可以把它看做一种 5.0 出的 ToolBar,先感受一下 AppBarLayout + CoordinatorLayout 的魅力。 实际效果就是这样,当向上滑动 View 的时候,ToolBar 会小时,向下滑动的时候,ToolBar 又会出现,但别忘了,这是 AppBarLayout 的功能,ToolBar 可办不到。由于要滑动,那么我们的 AppBarLayout 一定是和可以滑动的 View 一起使用的,比如 RecyclerView, ScollView 等。 我们看看上面的到底怎么实现的: <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_coor_app_bar" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.nanchen.coordinatorlayoutdemo.CoorAppBarActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_scrollFlags="scroll|enterAlways"> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/recycler" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> </android.support.design.widget.CoordinatorLayout> 我们可以看到,上面出现了一个 app:layouy_scrollFrags 的自定义属性设置,这个属性可以定义我们不同的滚动行为。 **2、layout_scrollFlags ** 根据官方文档,layout_scrollFlags 的取值可以为以下几种。 scroll 设成这个值的效果就好比本 View 和 Scrolling view 是“一体”的。具体示例我们在上面已经给出。有一点特别需要我们的注意,为了其他的滚动行为生效,必须同时指定 Scroll 和相应的标记,比如我们想要 exitUntilCollapsed 所表现的滚动行为,必须将 layout_scrollFlags 指定为 scroll|exitUntilCollapsed 。 exitUntilCollapsed 当本 View 离开屏幕时,会被“折叠”直到达到其最小高度。我们可以这样理解这个效果:当我们开始向上滚动 Scrolling view 时,本 View 会先接管滚动事件,这样本 View 会先进行滚动,直到滚动到了最小高度(折叠了),Scrolling view 才开始实际滚动。而当本 View 已完全折叠后,再向下滚动 Scrolling view,直到 Scrolling view 顶部的内容完全显示后,本 View 才会开始向下滚动以显现出来。 enterAlways 当 Scrolling view 向下滚动时,本 View 会一起跟着向下滚动。实际上就好比我们同时对 Scrolling view 和本 View 进行向下滚动。 enterAlwaysCollapsed 从名字上就可以看出,这是在 enterAlways 的基础上,加上了“折叠”的效果。当我们开始向下滚动 Scrolling View 时,本 View 会一起跟着滚动直到达到其“折叠高度”(即最小高度)。然后当 Scrolling View 滚动至顶部内容完全显示后,再向下滚动 Scrolling View,本 View 会继续滚动到完全显示出来。 snap 在一次滚动结束时,本 View 很可能只处于“部分显示”的状态,加上这个标记能够达到“要么完全隐藏,要么完全显示”的效果。 四、CollapsingToolBarLayout 这个东西,我相信很多博客和技术文章都会把 CollapsingToolBarLayout 和 CoordinatorLayout 放一起讲,这个东西的确很牛。我们同样先看看官方文档介绍: CollapsingToolbarLayout 通常用来在布局中包裹一个 Toolbar,以实现具有“折叠效果“”的顶部栏。它需要是 AppBarLayout 的直接子 View,这样才能发挥出效果。 CollapsingToolbarLayout包含以下特性: Collasping title(可折叠标题):当布局完全可见时,这个标题比较大;当折叠起来时,标题也会变小。标题的外观可以通过 expandedTextAppearance 和 collapsedTextAppearance 属性来调整。 Content scrim(内容纱布):根据 CollapsingToolbarLayout 是否滚动到一个临界点,内容纱布会显示或隐藏。可以通过 setContentScrim(Drawable) 来设置内容纱布。 Status bar scrim(状态栏纱布):也是根据是否滚动到临界点,来决定是否显示。可以通过 setStatusBarScrim(Drawable) 方法来设置。这个特性只有在 Android 5.0 及其以上版本,我们设置 fitSystemWindows 为 ture 时才能生效。 Parallax scrolling children(视差滚动子 View):子 View 可以选择以“视差”的方式来进行滚动。(视觉效果上就是子 View 滚动的比其他 View 稍微慢些) Pinned position children:子 View 可以选择固定在某一位置上。 上面的描述有些抽象,实际上对于 Content scrim 、Status bar scrim 我们可以暂时予以忽略,只要留个大概印象待以后需要时再查阅相关资料即可。下面我们通过一个常见的例子介绍下 CollapsingToolbarLayout 的基本使用姿势。 我们来看看一个常用的效果: 看看布局: <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout 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" android:id="@+id/activity_coor_tool_bar" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.nanchen.coordinatorlayoutdemo.CoorToolBarActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:fitsSystemWindows="true" android:layout_width="match_parent" android:layout_height="wrap_content" app:theme="@style/AppTheme.AppBarOverlay"> <android.support.design.widget.CollapsingToolbarLayout android:layout_width="match_parent" android:layout_height="200dp" app:contentScrim="@color/colorPrimary" app:expandedTitleMarginStart="100dp" app:layout_scrollFlags="scroll|exitUntilCollapsed|snap" app:statusBarScrim="@android:color/transparent" app:titleEnabled="false"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:scaleType="centerCrop" android:src="@mipmap/logo" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.6"/> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" app:popupTheme="@style/AppTheme.PopupOverlay" app:title=""/> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/recycler" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <TextView android:id="@+id/toolbar_title" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:layout_marginLeft="16dp" android:layout_marginTop="-100dp" android:alpha="0" android:elevation="10dp" android:gravity="center_vertical" android:text="爱吖校推-你关注的,我们才推" android:textColor="@android:color/white" android:textSize="20sp" android:textStyle="bold" app:layout_behavior=".SimpleViewBehavior" app:svb_dependOn="@id/appbar" app:svb_dependType="y" app:svb_targetAlpha="1" app:svb_targetY="0dp"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" android:src="@mipmap/ic_start" app:layout_anchor="@id/appbar" app:layout_anchorGravity="bottom|right"/> </android.support.design.widget.CoordinatorLayout> 我们在 XML 文件中为 CollapsingToolBarLayout 的 layout_scrollFlags 指定为 scroll|exitUntilCollapsed|snap,这样便实现了向上滚动的折叠效果。 CollapsingToolbarLayout 本质上同样是一个 FrameLayout,我们在布局文件中指定了一个 ImageView 和一个 Toolbar。ImageView 的layout_collapseMode 属性设为了 parallax,也就是我们前面介绍的视差滚动;而 Toolbar 的 layout_collaspeMode 设为了 pin ,也就是 Toolbar 会始终固定在顶部。 五、写在最后 本次的 Design 包下的 CoordinatorLayout 和 AppBarLayout 就讲述到这里,后续还将持续更新,欢迎拍砖~ 查看源码请移步 Github:https://github.com/nanchen2251/CoordinatorAppBarDemo 做不完的开源,写不完的矫情。欢迎扫描下方二维码或者公众号搜索「nanchen」关注我的微信公众号,目前多运营 Android ,尽自己所能为你提升。如果你喜欢,为我点赞分享吧~ nanchen

优秀的个人博客,低调大师

云数据库POLARDB优势解读系列文章之⑤——会话读一致性

作者 武藏等 POLARDB架构 我们知道,POLARDB是一个由多个节点构成的数据库集群,一个主节点,多个读节点。对外默认提供两个地址,一个是集群地址,一个是主地址,推荐使用集群地址,因为它具备读写分离功能可以把所有节点的资源整合到一起对外提供服务。 MySQL读写分离解决和引入的问题 用过MySQL的都知道,MySQL的主从复制简单易用,非常流行,通过把主库的Binlog异步地传输到备库并实时应用,一方面可以实现高可用,另一方面备库也可以提供查询,来减轻对主库的压力。 虽然备库可以提供查询,但存在两个问题,一是主库和备库一般提供两个不同的访问地址,应用程序端需要选择使用哪一个,对应用有侵入。二来MySQL的复制是异步的,即使是半同步也没办法做到100%强同步,因此备库的数据并不是最新的,有延迟,无法保证查询的一致性。 为了解决第一个问题,

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册