深入理解ViewPager2原理特性及其实践(上篇)
文章目录
- ViewPager2介绍
- ViewPager2优势
- ViewPager2使用
- 基于ViewPager2实现的Banner效果图
- 基本使用
- 进阶使用
- Fragment懒加载
- 一屏多页
- ViewPager2嵌套滑动冲突
- 支持DiffUtil增量更新
- 支持转场动画Transformer
- 源码浅析
- RecyclerView缓存机制
- offscreenPageLimit离屏缓存
- FragmentStateAdapter缓存原理
- 结论
- ViewPager、ViewPager2差异对比
- 参考
ViewPager2介绍
ViewPager2(以下简称VP2)
是 ViewPager(以下简称VP)
库的改进版本,内部使用RecyclerView
实现,可以把VP2
理解为每个ItemView
都充满全屏的RecyclerView
,VP2
可提供增强型功能并解决使用 VP
时遇到的一些常见问题。
ViewPager2优势
- 横向、垂直方向布局支持
设置VP2布局的android:orientation="vertical"
即可轻松完成垂直方向滑动。 - RTL(right-to-left)从右到左布局支持
设置VP2布局的android:layoutDirection="rtl"
即可。 - 一键禁止用户滑动支持
通过setUserInputEnabled()
设置是否禁止用户滑动。 - 可修改的Fragment集合
VP2
支持对可修改的Fragment
集合进行分页浏览,在底层集合发生更改时调用notifyDatasetChanged()
来更新界面。这意味着,您的应用可以在运行时动态修改Fragment
集合,而VP2
会正确显示修改后的集合。 - 支持DiffUtil
VP2
在RecyclerView
的基础上构建而成,这意味着它可以访问DiffUtil
实用程序类。所以VP2
支持当数据变化时进行局部更新,而不用通过notifyDatasetChanged()
全量更新。 - 支持模拟拖拽
fakeDragBy
ViewPager2使用
基于ViewPager2实现的Banner效果图
功能 | 示例 |
---|---|
基本使用 | |
仿淘宝搜索栏上下轮播 |
上述示例效果源码参见:lib_viewpager2,会在下篇中进行详细介绍。
基本使用
VP2不同于VP,需要单独引入:
dependencies {implementation "androidx.viewpager2:viewpager2:1.0.0"
}
声明XML布局:
<androidx.viewpager2.widget.ViewPager2android:id="@+id/view_pager2"android:layout_width="match_parent"android:layout_height="0dp"app:layout_constraintDimensionRatio="2:3"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" />
设置Adapter:
因为VP2
内部是RecyclerView
实现的,所以简单的界面直接继承RecyclerView.Adapter
:
class VpAdapter : RecyclerView.Adapter<VpAdapter.VpViewHolder>() {// adapter的数据源private var data: MutableList<HouseItem> = mutableListOf()fun setData(list: MutableList<HouseItem>) {data.clear()data.addAll(list)notifyDataSetChanged()}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VpViewHolder {//......}override fun onBindViewHolder(holder: VpViewHolder, position: Int) {}override fun getItemCount() = data.sizeclass VpViewHolder(_itemView: View) : RecyclerView.ViewHolder(_itemView) {//......}
}
如果需要使用到Fragment
,那么需要继承FragmentStateAdapter
:
const val PAGES_NUM = 4class ViewPager2Adapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {private val mItems: ArrayList<VP2Model> = arrayListOf()override fun getItemCount(): Int = PAGES_NUMoverride fun createFragment(position: Int): Fragment {log("pos:$position: createFragment()")return VP2Fragment(position)}override fun onBindViewHolder(holder: FragmentViewHolder,position: Int,payloads: MutableList<Any>) {super.onBindViewHolder(holder, position, payloads)log("pos:$position: onBindViewHolder()")}override fun getItemId(position: Int): Long {return super.getItemId(position)}override fun containsItem(itemId: Long): Boolean {return super.containsItem(itemId)}fun setModels(newItems: List<VP2Model>) {//不借助DiffUtil更新数据//mItems.clear()//mItems.addAll(newItems)//notifyDataSetChanged()//借助DiffUtil更新数据val callback = PageDiffUtil(mItems, newItems)val difResult = DiffUtil.calculateDiff(callback)mItems.clear()mItems.addAll(newItems)difResult.dispatchUpdatesTo(this)}
}
在Activity/Fragment中调用:
//mVP2Adapter = VpAdapter() //RecyclerView.Adapter
mVP2Adapter = ViewPager2Adapter(this) //FragmentStateAdapter
VP2.adapter = mVP2Adapter
进阶使用
Fragment懒加载
一屏多页
设置一屏多页的关键代码如下:
VP2.apply {//下面是关键代码val recyclerView = getChildAt(0) as RecyclerViewrecyclerView.apply {val padding = 50// setting padding on inner RecyclerView puts overscroll effect in the right placesetPadding(padding, 0, padding, 0)clipToPadding = false}adapter = Adapter()
}
在VP2
源码内部第254行,RecyclerView
固定索引为0:
attachViewToParent(mRecyclerView, 0, mRecyclerView.getLayoutParams());
所以可以通过VP2.getChildAt(0)
直接获取VP2
内部的RecyclerView
,进而通过设置padding
来实现一屏多页,运行效果如下:
ViewPager2嵌套滑动冲突
因为VP2
内部是通过RecyclerView
实现的,所以滑动相关处理主要在RecyclerView
中进行,其内部实现:
private class RecyclerViewImpl extends RecyclerView {RecyclerViewImpl(@NonNull Context context) {super(context);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {return isUserInputEnabled() && super.onInterceptTouchEvent(ev);}
}
onInterceptTouchEvent
中会进行事件拦截,可以看到源码中的onInterceptTouchEvent
只是多了isUserInputEnabled
的判断,其他的都没有处理,
所以官方并没有对VP2
的嵌套滑动进行处理,需要开发者进行自行处理,这里可以通过事件传递中的内部拦截法(requestDisallowInterceptTouchEvent()
)
进行处理,如果嵌套滑动中的内部控件需要滑动时,就控制外部父控件不拦截事件,设置为requestDisallowInterceptTouchEvent(true)
;反之则让外部父控件拦截事件,设置为requestDisallowInterceptTouchEvent(false)
。官方Demo
中也给出了对应例子:NestedScrollableHost:
class NestedScrollableHost : FrameLayout {constructor(context: Context) : super(context)constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)private var touchSlop = 0private var initialX = 0fprivate var initialY = 0fprivate val parentViewPager: ViewPager2?get() {var v: View? = parent as? Viewwhile (v != null && v !is ViewPager2) {v = v.parent as? View}return v as? ViewPager2}private val child: View? get() = if (childCount > 0) getChildAt(0) else nullinit {touchSlop = ViewConfiguration.get(context).scaledTouchSlop}private fun canChildScroll(orientation: Int, delta: Float): Boolean {val direction = -delta.sign.toInt()return when (orientation) {0 -> child?.canScrollHorizontally(direction) ?: false1 -> child?.canScrollVertically(direction) ?: falseelse -> throw IllegalArgumentException()}}override fun onInterceptTouchEvent(e: MotionEvent): Boolean {handleInterceptTouchEvent(e)return super.onInterceptTouchEvent(e)}private fun handleInterceptTouchEvent(e: MotionEvent) {val orientation = parentViewPager?.orientation ?: return// Early return if child can't scroll in same direction as parentif (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) {return}if (e.action == MotionEvent.ACTION_DOWN) {initialX = e.xinitialY = e.yparent.requestDisallowInterceptTouchEvent(true)} else if (e.action == MotionEvent.ACTION_MOVE) {val dx = e.x - initialXval dy = e.y - initialYval isVpHorizontal = orientation == ORIENTATION_HORIZONTAL// assuming ViewPager2 touch-slop is 2x touch-slop of childval scaledDx = dx.absoluteValue * if (isVpHorizontal) .5f else 1fval scaledDy = dy.absoluteValue * if (isVpHorizontal) 1f else .5fif (scaledDx > touchSlop || scaledDy > touchSlop) {if (isVpHorizontal == (scaledDy > scaledDx)) {// Gesture is perpendicular, allow all parents to interceptparent.requestDisallowInterceptTouchEvent(false)} else {// Gesture is parallel, query child if movement in that direction is possibleif (canChildScroll(orientation, if (isVpHorizontal) dx else dy)) {// Child can scroll, disallow all parents to interceptparent.requestDisallowInterceptTouchEvent(true)} else {// Child cannot scroll, allow all parents to interceptparent.requestDisallowInterceptTouchEvent(false)}}}}}
}
支持DiffUtil增量更新
class PageDiffUtil(private val oldModels: List<Any>, private val newModels: List<Any>) :DiffUtil.Callback() {/*** 旧数据*/override fun getOldListSize(): Int = oldModels.size/*** 新数据*/override fun getNewListSize(): Int = newModels.size/*** DiffUtil调用来决定两个对象是否代表相同的Item。true表示两个Item相同(表示View可以复用),false表示不相同(View不可以复用)* 例如,如果你的项目有唯一的id,这个方法应该检查它们的id是否相等。*/override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {return oldModels[oldItemPosition]::class.java == newModels[newItemPosition]::class.java}/*** 比较两个Item是否有相同的内容(用于判断Item的内容是否发生了改变),* 该方法只有当areItemsTheSame (int, int)返回true时才会被调用。*/override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {return oldModels[oldItemPosition] == newModels[newItemPosition]}/*** 该方法执行时机:areItemsTheSame(int, int)返回true 并且 areContentsTheSame(int, int)返回false* 该方法返回Item中的变化数据,用于只更新Item中变化数据对应的UI*/override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {return super.getChangePayload(oldItemPosition, newItemPosition)}
}
调用方式:
//使用DiffUtil更新数据
val callback = PageDiffUtil(mItems, newItems)
val difResult = DiffUtil.calculateDiff(callback)
mItems.clear()
mItems.addAll(newItems)
difResult.dispatchUpdatesTo(adapter)
注意:如果想异步进行数据比较,可以使用AsyncListDiffer 或者RecyclerView中的ListAdapter。
支持转场动画Transformer
调用方式:ViewPager2.setPageTransformer(transformer),如果同时想执行多个Transformer,可以像下面这样写:
val multiTransformer = CompositePageTransformer()
multiTransformer.addTransformer(ScaleInTransformer())
multiTransformer.addTransformer(MarginPageTransformer(10))
ViewPager2.setPageTransformer(multiTransformer)
源码浅析
RecyclerView缓存机制
因为VP2
内部基于RecyclerView
,所以VP2
的缓存也是基于RecyclerView
缓存机制实现的,直接来看RecyclerView
的缓存机制:
缓存 | 涉及对象 | 作用 | 重新创建视图View(onCreateViewHolder) | 重新绑定数据(onBindViewHolder) |
---|---|---|---|---|
一级缓存 | mAttachedScrap | 缓存屏幕中可见范围的ViewHolder | false | false |
二级缓存 | mCachedViews | 缓存滑动时即将与RecyclerView分离的ViewHolder,按子View的position或id缓存,默认最多存放2个 | false | false |
三级缓存 | mViewCacheExtension | 开发者自行实现的缓存 | - | - |
四级缓存 | mRecyclerPool | ViewHolder缓存池,本质上是一个SparseArray,其中key是ViewType(int类型),value存放的是 ArrayList< ViewHolder>,默认每个ArrayList中最多存放5个ViewHolder | false | true |
RecyclerView
缓存机制更详细解析参见:Android深入理解RecyclerView的缓存机制 。在VP2
中主要使用的是mCachedViews
、mRecyclerPool
:
mCachedViews
:缓存滑动时即将与RecyclerView
页面分离的ViewHolder
,按子View
的position
或id
缓存,默认存放2个,可以通过setItemViewCacheSize(int size)
修改缓存个数。如果RecyclerView
开启了预抓取功能(默认预抓取个数为1),则缓存池大小默认为3(mCachedViews缓存2 + 预抓取个数1 )。mRecyclerPool
:ViewHolder
缓存池,本质上是一个SparseArray
,其中key
是ViewType(int类型)
,value
存放的是ArrayList< ViewHolder>
,默认每个ArrayList
中最多存放5个ViewHolder
。回收到该缓存池的ViewHolder
会将数据解绑,当复用该ViewHolder
时,需要重新绑定数据(即重新走(onBindViewHolder
)。
offscreenPageLimit离屏缓存
//ViewPager2.java
public void setOffscreenPageLimit(@OffscreenPageLimit int limit) {if (limit < 1 && limit != OFFSCREEN_PAGE_LIMIT_DEFAULT) {throw new IllegalArgumentException("Offscreen page limit must be OFFSCREEN_PAGE_LIMIT_DEFAULT or a number > 0");}mOffscreenPageLimit = limit;// Trigger layout so prefetch happens through getExtraLayoutSize()mRecyclerView.requestLayout();
}
setOffscreenPageLimit
设置的是VP2
的离屏显示个数,默认是-1,因为RecyclerView
中的布局是通过LayoutManager
,所以真正进行离屏计算是在VP2.LinearLayoutManagerImpl#calculateExtraLayoutSpace()
中,该方法计算的是LinearLayoutManager
布局的额外空间,LinearLayoutManagerImpl
继承自LinearLayoutManager
:
protected void calculateExtraLayoutSpace(@NonNull RecyclerView.State state,@NonNull int[] extraLayoutSpace) {int pageLimit = getOffscreenPageLimit();if (pageLimit == OFFSCREEN_PAGE_LIMIT_DEFAULT) {// Only do custom prefetching of offscreen pages if requestedsuper.calculateExtraLayoutSpace(state, extraLayoutSpace);return;}final int offscreenSpace = getPageSize() * pageLimit;extraLayoutSpace[0] = offscreenSpace;extraLayoutSpace[1] = offscreenSpace;
}
getPageSize()
表示ViewPager2
的宽度,左右离屏大小都为getPageSize() * pageLimit
。extraLayoutSpace[0]
表示左边,extraLayoutSpace[1]
表示右边。比如设置offscreenPageLimit
为1,可以认为是把PageSize
扩大到3倍。左右两边各有一个离屏PageSize
的宽度,如图所示:
FragmentStateAdapter缓存原理
FragmentStateAdapter
的使用前面已经介绍过了,因为FragmentStateAdapter
继承自RecyclerView.Adapter
,所以可以直接通过setAdapter
设置给VP2
。我们知道FragmentStateAdapter
作为Adapter
时,每个Item
都是Fragment
,那么Fragment
又是怎么跟FragmentStateAdapter
关联起来的呢?下面就尝试分析一下:
//FragmentStateAdapter.javafinal LongSparseArray<Fragment> mFragments = new LongSparseArray<>();private final LongSparseArray<Integer> mItemIdToViewHolder = new LongSparseArray<>();public abstract @NonNull Fragment createFragment(int position);@NonNull@Overridepublic final FragmentViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {return FragmentViewHolder.create(parent);}//FragmentViewHolder.javapublic final class FragmentViewHolder extends ViewHolder {private FragmentViewHolder(@NonNull FrameLayout container) {super(container);}@NonNull static FragmentViewHolder create(@NonNull ViewGroup parent) {FrameLayout container = new FrameLayout(parent.getContext());container.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));//设置唯一IDcontainer.setId(ViewCompat.generateViewId());container.setSaveEnabled(false);return new FragmentViewHolder(container);}@NonNull FrameLayout getContainer() {return (FrameLayout) itemView;}}
在onCreateViewHolder
中设置的是名为FragmentViewHolder
的ViewHolder
,内部的根布局是一个FrameLayout
,为该FrameLayout
设置一个唯一ID
,后续复用ViewHolder
及Fragment的
布局时会使用。FragmentStateAdapter
内部两个很有用的数据结构:
final LongSparseArray<Fragment> mFragments = new LongSparseArray<>();private final LongSparseArray<Integer> mItemIdToViewHolder = new LongSparseArray<>();
mFragments
:是position
与Fragment
的映射表。随着position
的增长,Fragment
是会不断的新建出来的。Fragment
可以被缓存起来,当它被回收后无法重复使用。mItemIdToViewHolder
:是position
与ViewHolder
的Id
的映射表。由于ViewHolder
是RecyclerView
缓存机制的载体。所以随着position
的增长,ViewHolder
并不会像Fragment
那样不断的新建出来,而是会充分利用RecyclerView
的复用机制。
当VP2
滑动时,离当前正在显示的Item
的前面最近的2个会被缓存到mCachedViews
中,超过2个时会从mCachedViews
删除,并将其转移到RecyclerPool
中,此时会调用onViewRecycled()
如下:
@Override
public final void onViewRecycled(@NonNull FragmentViewHolder holder) {final int viewHolderId = holder.getContainer().getId();final Long boundItemId = itemForViewHolder(viewHolderId); // item currently bound to the VHif (boundItemId != null) {removeFragment(boundItemId);mItemIdToViewHolder.remove(boundItemId);}
}
当ViewHolder
回收到RecyclerPool
中时,将ViewHolder
相关的信息删除。在前面的介绍中我们知道从mCachedViews
中取ViewHolder
时并不会执行onBindViewHolder
,只有从RecyclerPool
取ViewHolder
时才会执行到onBindViewHolder
,接着看一下onBindViewHolder
:
@Overridepublic final void onBindViewHolder(final @NonNull FragmentViewHolder holder, int position) {//如果mItemIdToViewHolder中跟当前ViewHolder的ID一样,那么需要将mItemIdToViewHolder中的ID进行删除,并在后面重新对该ViewHolder的ID进行赋值final long itemId = holder.getItemId();final int viewHolderId = holder.getContainer().getId();final Long boundItemId = itemForViewHolder(viewHolderId); // item currently bound to the VHif (boundItemId != null && boundItemId != itemId) {removeFragment(boundItemId);mItemIdToViewHolder.remove(boundItemId);}//在这里将viewHolerId重新添加到mItemIdToViewHolder中mItemIdToViewHolder.put(itemId, viewHolderId); // this might overwrite an existing entry//创建Fragment并添加到mFragments中ensureFragment(position);final FrameLayout container = holder.getContainer();if (ViewCompat.isAttachedToWindow(container)) {//...其他...container.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {@Overridepublic void onLayoutChange(View v, int left, int top, int right, int bottom,int oldLeft, int oldTop, int oldRight, int oldBottom) {if (container.getParent() != null) {container.removeOnLayoutChangeListener(this);//将新来的Fragment的布局依附到ViewHolder中placeFragmentInViewHolder(holder);}}});}gcFragments();}//onBindViewHolder()中调用该方法创建Fragmentprivate void ensureFragment(int position) {long itemId = getItemId(position);if (!mFragments.containsKey(itemId)) {//在这里创建Fragment Fragment newFragment = createFragment(position);newFragment.setInitialSavedState(mSavedStates.get(itemId));mFragments.put(itemId, newFragment);}}
可以看到在onBindViewHolder()
中创建了Fragment
并将其添加到了mFragments
中,从而Fragment
跟FragmentStateAdapter
关联起来了。
默认当前Item
的前面2个及后面的1个(RecyclerView
默认会开启预抓取能力:isItemPrefetchEnabled
默认为true
)总共3个Fragment
会缓存在mCachedViews
中;超过2个的位置时创建的Fragment
就会被销毁,有一种特殊情况需要注意:当VP2
滑动到最后时,当前Item
前面的3个(这里不是默认的2个了)Fragment
都会被缓存,因为滑动到最后了,后面预抓取的1个给到了前面。
结论
以从左到右布局且当前向右滑为例:
- 当没有设置
offscreenPageLimit
离屏缓存时,VP2
中的RecyclerView
默认会缓存左侧的2个Item
(缓存在mCachedViews
)以及右侧的1个Item
。 注意一点:当第一次加载时,由于还没有触发VP2
的onTouch
操作,所以此时还不会进行右侧的预抓取。 - 如果设置了
offscreenPageLimit
为1,则左右离屏各新增一个缓存的Item
,可以直观理解系统会默认把画布宽度增加到3倍(左右这两个默认不可见),加上RecyclerView
默认缓存的3个,除了当前显示的Item
,还会缓存总共5个Item
。
ViewPager、ViewPager2差异对比
功能 | ViewPager | ViewPager2 |
---|---|---|
Listener | addPageChangeListener | registerOnPageChangeCallback(OnPageChangeCallback callback),其中OnPageChangeCallback是一个抽象类,不同于接口方式,抽象类里用到哪个覆写哪个即可 |
Fragment | FragmentPagerAdapter、FragmentStatePagerAdapter | FragmentStateAdapter |
setOffscreenPageLimit(int num) | 离屏缓存,当设置小于1时,会强制设为1,即强制左右各缓存1个 | OFFSCREEN_PAGE_LIMIT_DEFAULT默认为-1,及默认不会离屏缓存 |
Adapter | PagerAdapter | RecyclerView.Adapter |
其他操作 | / | 支持RTL从右到左排序、垂直滑动、停止用户操作 |
参考
【1】官方:使用 ViewPager2 在 Fragment 之间滑动
【2】官方:从 ViewPager 迁移到 ViewPager2
【3】ViewPager2中的Fragment懒加载实现方式
【4】聊聊ViewPager2中的缓存和复用机制
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 前端-微前端
什么是微前端? 单实例: 即同一时刻只要一个子应用被展示,子应用具备一个完整的生命周期 多实例: 通常用URL的转换来切换子应用 系统的稳定性 当一个实际的系统处于一个平衡的状态时,如果受到外来作用的影响时,系统经过…...
2024/4/28 2:07:53 - 可视化面板 docker 镜像是什么,commit自己的镜像
portainer docker run -d -p 8088:9000 --restartalways -v /var/run/docker.sock:/var/run /docker.sock --privilegedtrue portainer/portainer 进去之后的面板 如何得到镜像: 1.从远程仓库下载 2.朋友拷贝给你 3.自己制作一个镜像dockerfile commit 镜像 …...
2024/4/28 12:34:31 - 讲讲我的初识前端
前端入坑是源于一个同事,两个人聊起天的时候,讲到了这个行业的发展前景,首先声明,我不是计算机专业的,算是零入坑了,目前入坑接近一年的时间,这个坑...目前觉得还是很有成就感的...
2024/4/28 7:09:28 - 基于AntDesignVue的自定义Dropdown下拉选择组件
组件效果 组件代码 <template><a-dropdown :trigger"[trigger]"><div class"dropdownTitle"><span v-text"defaultText"/><a-icon type"down" /></div><a-menu slot"overlay">&…...
2024/4/28 14:50:20 - 快速原型工具,帮你从0开始画原型图
最近5G冲浪的时候,我常常会接触到这样一些问题,例如“该不该画高保真的原型图”、“有必要把原型做成demo的形式吗?”“产品经理不写PRD,只画原型合适吗?” 那当然不合适啦! Emmmmm 私以为,还是…...
2024/4/28 2:29:12 - Spring 入门必读
写在最前 Spring 是 Java 企业级应用的开源开发框架。Spring 主要用来开发 Java 应用,但有些扩展是针对构建 J2EE 平台的 WEB 应用。Spring 框架目标是简化 Java 企业级应用开发,并通过 POJO 为基础的编程模型促进良好的编程习惯。 Spring 官网 Sprin…...
2024/4/13 22:53:22 - 55ide游戏引擎教程3:图片加载显示
55ide引擎图片创建显示有两种方式。当然,我们主要讲通过代码来进行展示。好了,过年了,废话不多说,留着喝酒时候再说。 1、到资源库加载一张图片 引擎界面左侧,项目,上面有图片资源。 此时,我们…...
2024/4/28 9:50:49 - C语言string.h库函数的介绍、使用及部分代码实现。
目录 一、strlen()函数 1、strlen函数简介 2、strlen函数模拟实现 二、strcpy()函数及strncpy()函数 1、strcpy函数及strncpy函数简介 2、strcpy函数及strncpy函数模拟实现 三、strcat()函数及strncat()函数 1、strcat()函数及strncat()函数简介 2、strcat()函数及strn…...
2024/4/28 8:04:32 - OkHttp 3,又是一年金九银十
而对于同步任务,Dispatcher只是简单记录当前运行的任务实体(RealCall),并且是由RealCall主动注册和注销。 Dispatcher是final类,不提供扩展接口,但是Dispatcher存在两个构造方法:Dispatcher()和…...
2024/4/28 3:22:05 - 重新安装croedns
删除已有podkubectl delete --namespacekube-system deployment coredns Bash 重新安装wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/coredns.yaml.sed wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/deploy…...
2024/4/13 22:53:47 - Python学习笔记(数据结构和面向对象)(1)
Python基础语法Python数据结构Python面向对象Python数据结构 Python数据结构有:数字、字符串、列表、元组、字典 1.数字:Python Number 数据类型用于存储数值,包括整型、长整型、浮点型、复数。 (1)Python math 模…...
2024/4/7 18:48:12 - Linux网络学习总结(二)
本系列网络学习是学习狄泰软件学院唐佐林老师课程后所作总结 1、TCP/IP 共分为五层(从上至下):应用层、传输层(TCP/UDP)、网络层(IP)、数据链路层、物理层。上层依赖下层提供的服务/能力 应用层:各个应用程序可以定义(使用)各种各样的协议 传输…...
2024/4/5 3:38:57 - (纯C语言版)国王的金币<洛谷>
小伙伴们,“国王的金币”作为一道初学者的算法题,相信大家都做过吧~下面我将把我的代码(纯C语言版)展示在下方,思路会发表在另外一篇博客中,尽情期待哟。 题目: 当连续n天每天收到n枚金币后&a…...
2024/4/5 3:38:56 - sakura frp使用开机自启设置
sakura frpc支持局域网穿透,有了它你可以从任何地方访问你的树苺派, 不过sakura frpc用起来有点复杂,这里记录下。 设置隧道 先要等落sakura 官方网站申请注册个帐号,实名制后申请个隧道: 上图中要记住这个隧道的id和…...
2024/4/13 22:53:32 - 297. 二叉树的序列化与反序列化
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。 请设计一个算法来实现二叉树的序列化与反序列化。这里…...
2024/4/13 22:53:52 - polkit 的 pkexec 中的本地权限提升 (CVE-2021-4034)
内容概括 分析 开发 致谢 时间线 概括我们发现了本地特权升级(从任何用户到 root) polkit 的 pkexec,一个 SUID 根程序,默认安装在 每个主要的 Linux 发行版:“Polkit(以前称为 PolicyKit)是一…...
2024/4/13 22:53:42 - MySQL 安装成功后,首次基本配置
登录MySQL后,使用 ?查看帮助, mysql> ? For information about MySQL products and services, visit: http://www.mysql.com/ For developer information, including the MySQL Reference Manual, visit: http://dev.mysql.com/ To buy …...
2024/4/13 22:53:52 - 架构抽象之通用流程管理抽象
通用流程管理要做些什么 通用流程管理旨在抽象出流程部分,让流程与业务进行松耦合,那么这个抽象过程就需要考虑出完整的结构,以适合尽可能多的业务。我们通常做项目的时候,都把业务流程两个词儿放到一起考虑,其实我们…...
2024/4/19 8:07:44 - 使用 Python 程序实现摩斯密码翻译器|Python 主题月
摩斯密码是一种将文本信息作为一系列通断的音调、灯光或咔嗒声传输的方法,无需特殊设备,熟记的小伙伴即可直接翻译。它以电报发明者Samuel F. B. Morse的名字命名。 算法 算法非常简单。英语中的每个字符都被一系列“点”和“破折号”代替,…...
2024/4/13 22:53:47 - 测试第六天学python--forwhile
1.for循环语法 for 变量名 in 某数据类型(包括:字符串、列表、元组、字典、集合等) 代码块 for循环的循环次数由数据的元素个数决定 遍历变量的元素 ppython#字符串 b[1,2,3] #列表 d {"age":18,"name":"小白&q…...
2024/4/7 18:48:07
最新文章
- 【Harmony3.1/4.0】笔记三-计算器
概念 网格布局是由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。网格布局具有较强的页面均分能力,子组件占比控制能力,是一种重要自适应布局,其使用场景有九宫格图片展示、日历、计算器等…...
2024/4/29 2:06:23 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - 阿里云8核32G云服务器租用优惠价格表,包括腾讯云和京东云
8核32G云服务器租用优惠价格表,云服务器吧yunfuwuqiba.com整理阿里云8核32G服务器、腾讯云8核32G和京东云8C32G云主机配置报价,腾讯云和京东云是轻量应用服务器,阿里云是云服务器ECS: 阿里云8核32G服务器 阿里云8核32G服务器价格…...
2024/4/28 23:07:39 - 数据结构--KMP算法
数据结构–KMP算法 首先我在这里提出以下问题,一会一起进行探讨 1.什么是最长公共前后缀 2. KMP算法怎么实现对匹配原理 3. 最长公共前后缀怎么求解 KMP算法可以用来解决什么问题? 答:在字符串中匹配子串,也称为模式匹配 分析…...
2024/4/27 22:32:52 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/4/28 13:52:11 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/4/28 3:28:32 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/4/26 23:05:52 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/4/28 13:51:37 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/4/27 17:58:04 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/4/27 14:22:49 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/4/28 1:28:33 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/4/28 15:57:13 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/4/27 17:59:30 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/4/25 18:39:16 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/4/28 1:34:08 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/4/26 19:03:37 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/4/28 1:22:35 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/4/25 18:39:14 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/4/26 23:04:58 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/4/27 23:24:42 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/4/28 5:48:52 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/4/26 19:46:12 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/4/27 11:43:08 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/4/27 8:32:30 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) 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 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在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