RecyclerView性能优化及高级使用

article/2025/11/10 19:14:30

最近研究应用流畅度专题时,发现RecyclerView里边的坑真多,有很多可以优化的点,在理解优化点之前,最好对RecyclerView的缓存机制有一些了解,比如得知道CacheView和RecycledViewPool的区别和联系,RecyclerView的绘制流程有一定了解,再来谈RecyclerView的性能提升。缓存机制可以看看这篇文章:基于滑动场景解析RecyclerView的回收复用机制原理

还有一篇外国人写的,ViewHolder的探究,这篇文章把RecyclerView的各级缓存作用剖析得很清晰,以前看过很多人写的文章,感觉都是一知半解,总结下:

1、RecyclerView缓存

1.1 RecyclerView主要有三级缓存:

(1)Attached scrap & Changed scrap

ArrayList<ViewHolder> mAttachedScrap 

主要用在插入或是删除itemView时,先把屏幕内的ViewHolder保存至AttachedScrap中,作用在LayoutManager中,它仅仅把需要从ViewGroup中移除的子view设置它的父view为null,从而实现了从RecyclerView中移除操作detachView()。需要新插入的view从cacheView/Pool中找,没找到则createViewHolder。而从ViewGroup中移除的子view会放到Pool缓存池中,如下图中的itemView b。

ArrayList<ViewHolder> mChangedScrap :

主要用到刷新屏幕上的itemView数据,它不需要重新layout,notifyItemChanged()或者notifyItemRangeChanged()
(2) cache Views :保存最近移出屏幕的ViewHolder,包含数据和position信息,复用时必须是相同位置的ViewHolder才能复用,应用场景在那些需要来回滑动的列表中,当往回滑动时,能直接复用ViewHolder数据,不需要重新bindView。用一个数组保存ViewHolder,实现是:ArrayList<ViewHolder> mCachedViews 

(3) RecyclerViewPool :缓存池,当cacheView满了后,将cacheView中移出的ViewHolder放到Pool中,放之前会把ViewHolder数据清除掉,所以复用时需要重新bindView。实现是: SparseArray<ArrayList<ViewHolder>> mScrap;//按viewType来保存ViewHolder,每种类型最大缓存个数默认为5

1.2 RecyclerView缓存过程:

在滑动过程中,会先滑动的itemView保存到CacheView中,CacheView大小默认是2,如果超过了最大容量,则按FIFO,将队列头部的itemView出队,保存至缓存池RecyclerViewPool中,缓存池是按itemView的类型itemType来保存的,每种itemType默认缓存个数是5,超过了,则直接由GC回收。具体表现如下图:

可以看到CacheView缓存中蓝色的块一直最最近两个,而RecycledViewPool中,保存最大是5,超过5了后ViewHolder都被回收。

1.3 RecyclerView缓存寻找过程:

RecyclerView在找到可用ViewHodler的顺序是:如果在缓存CacheViews中找到,则直接复用;如果在缓存池RecycerViewPool找到,则需要bindView;如果没有找到可用的ViewHolder,则需要create新建一个ViewHolder,并bindView绑定view。

1.4 调用notifyDataSetChanged过程:

如果调用notifyDataSetChanged,每个itemView没有稳定的id的话,RecyclerView不知道接下来会发生什么,也不知道哪些改变,它假设所有都改变了,会将每一个ViewHolder设置成无效并且放到缓存池Pool中,如果我们仅是把屏幕上的第四条itemView移到第六条的位置,屏幕上所有itemView都会重新layout一遍,这样只能从缓存池RecycledViewPool池中取缓存的ViewHolder,如果不够时,需要重新create ViewHolder.具体实现如下:

如果设置了Stable Ids,即每一个itemView都有一个唯一的id来标识,通过getItemId()来获取这个唯一标识id,当然我们不能用position来标识,因为itemView会复用,位置会乱序。当调用notifyDataSetChanged()方法时,ViewHolder会进入上面的一级缓存mAttachedScrap中,而不是进入缓存池pool中,这样的好处:1)不会存在缓存池pool满的问题,不需要重新createViewHolder; 2) 不需要重新bindView了。

下面说说RecyclerView的一些优化方案和使用技巧:

1、recyclerView.setHasFixedSize(true);

当Item的高度如是固定的,设置这个属性为true可以提高性能,尤其是当RecyclerView有条目插入、删除时性能提升更明显。RecyclerView在条目数量改变,会重新测量、布局各个item,如果设置了setHasFixedSize(true),由于item的宽高都是固定的,adapter的内容改变时,RecyclerView不会整个布局都重绘。具体可用以下伪代码表示:

void onItemsInsertedOrRemoved() {if (hasFixedSize) layoutChildren();else requestLayout();
}

 

2、使用getExtraLayoutSpace为LayoutManager设置更多的预留空间

在RecyclerView的元素比较高,一屏只能显示一个元素的时候,第一次滑动到第二个元素会卡顿。  

RecyclerView (以及其他基于adapter的view,比如ListView、GridView等)使用了缓存机制重用子 view(即系统只将屏幕可见范围之内的元素保存在内存中,在滚动的时候不断的重用这些内存中已经存在的view,而不是新建view)。

这个机制会导致一个问题,启动应用之后,在屏幕可见范围内,如果只有一张卡片可见,当滚动的时 候,RecyclerView找不到可以重用的view了,它将创建一个新的,因此在滑动到第二个feed的时候就会有一定的延时,但是第二个feed之 后的滚动是流畅的,因为这个时候RecyclerView已经有能重用的view了。

如何解决这个问题呢,其实只需重写getExtraLayoutSpace()方法。根据官方文档的描述 getExtraLayoutSpace将返回LayoutManager应该预留的额外空间(显示范围之外,应该额外缓存的空间)。

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this) {@Overrideprotected int getExtraLayoutSpace(RecyclerView.State state) {return 300;}
};

3、RecyclerView 数据预取

android sdk>=21时,支持渲染(Render)线程,RecyclerView数据显示分两个阶段:

1)在UI线程,处理输入事件、动画、布局、记录绘图操作,每一个条目在进入屏幕显示前都会被创建和绑定view;

2)渲染(Render)线程把指令送往GPU。

数据预取的思想就是:将闲置的UI线程利用起来,提前加载计算下一帧的Frame Buffer

在新的条目进入视野前,会花大量时间来创建和绑定view,而在前一帧却可能很快完成了这些操作,导致前一帧的UI线程有一大片空闲时间。RecyclerView开发工程师将创建和绑定移到前一帧,使UI线程与渲染线程同时工作,在一个条目即将进入视野时预取数据。具体如下图,在前一帧的红色虚线圈中,UI线程有一定的空闲时间,可以把第二帧Create B的工作移到前一帧的空闲时间来完成。

具体实现方式是:在 RecyclerView 开始一个滚动时new Runnable对象,根据 layout manager 和滚动的方向预取即将进入视野的条目,可以同时取出一个或多个条目,例如在使用 GridLayoutManager 时新的一行马上要出现的时候。在 25.1 版本中,预取操作被分为单独的创建/绑定操作,比对整组条目操作更容易被纳入 UI 线程的空隙中。具体实现原理可参考:RecyclerView预加载机制源码分析

完成这些工作基本上没有任何代价,因为 UI 线程在两帧之间的空隙不做任何工作。我们可以使用这些空闲时间来完成将来的工作,并使得未来的帧出现得更快,

如果使用 RecyclerView 提供的LayoutManager,自动使用了这种优化操作。如果使用嵌套 RecyclerView 或者自己实现Layout Manager,则需要在代码中设置。

1)对于嵌套 RecyclerView,要获取最佳的性能,在内部的 LayoutManager 中调用 LinearLayoutManager.setInitialItemPrefetchCount()方法(25.1版本起可用)。

例如:如果竖直方向的list至少展示三个条目,调用 setInitialItemPrefetchCount(4)。

2)如果自己实现了LayoutManager,需要重写 LayoutManager.collectAdjacentPrefetchPositions()方法。该方法在数据预取开启时被 RecyclerView 调用(LayoutManager 的默认实现什么都不做)。在嵌套的内层 RecyclerView 中,如果想让LayoutManager 预取数据,同样应当实现 LayoutManager.collectInitialPrefetchPositions()。

4、避免创建过多对象

onCreateViewHolder 和 onBindViewHolder 对时间都比较敏感,尽量避免繁琐的操作和循环创建对象。例如创建 OnClickListener,可以全局创建一个。同时onBindViewHolder调用次数会多于onCreateViewHolder的次数,如从RecyclerViewPool缓存池中取到的View都需要重新bindView,所以我们可以把监听放到CreateView中进行。

优化前:

@Override
public void onBindViewHolder(ViewHolder holder, int position) {holder.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//do something}});
}

优化后:

private class XXXHolder extends RecyclerView.ViewHolder {private EditText mEt;EditHolder(View itemView) {super(itemView);mEt = (EditText) itemView;mEt.setOnClickListener(mOnClickListener);}}private View.OnClickListener mOnClickListener = new View.OnClickListener() {@Overridepublic void onClick(View v) {//do something}}

5、局部刷新

可以用一下一些方法,替代notifyDataSetChanged,达到局部刷新的目的。notifyDataSetChanged会触发所有item的detached回调再触发onAttached回调。

notifyItemChanged(int position)
notifyItemInserted(int position)
notifyItemRemoved(int position)
notifyItemMoved(int fromPosition, int toPosition) 
notifyItemRangeChanged(int positionStart, int itemCount)
notifyItemRangeInserted(int positionStart, int itemCount) 
notifyItemRangeRemoved(int positionStart, int itemCount) 
如果必须用 notifyDataSetChanged(),那么最好设置 mAdapter.setHasStableIds(true)

6、重写onScroll事件

对于大量图片的RecyclerView,滑动暂停后再加载;RecyclerView中存在几种绘制复杂,占用内存高的楼层类型,但是用户只是快速滑动到底部,并没有必要绘制计算这几种复杂类型,所以也可以考虑对滑动速度,滑动状态进行判断,满足条件后再加载这几种复杂的。

7、RecyclerView缓存

7.1 setItemViewCacheSize(int )

RecyclerView可以设置自己所需要的ViewHolder缓存数量,默认大小是2。cacheViews中的缓存只能position相同才可得用,且不会重新bindView,CacheViews满了后移除到RecyclerPool中,并重置ViewHolder,如果对于可能来回滑动的RecyclerView,把CacheViews的缓存数量设置大一些,可以减少bindView的时间,加快布局显示。

注:此方法是拿空间换时间,要充分考虑应用内存问题,根据应用实际使用情况设置大小。

网上大部分设置CacheView大小时都会带上:

setDrawingCacheEnabled(true)和setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH)

setDrawingCacheEnabled这个是View本身的方法,意途是开启缓存。通过setDrawingCacheEnabled把cache打开,再调用getDrawingCache就可以获得view的cache图片,如果cache没有建立,系统会自动调用buildDrawingCache方法来生成cache。一般截图会用到,这里的设置drawingcache,可能是在重绘时不需要重新计算bitmap的宽高等,能加快dispatchDraw的速度,但开启drawingcache,肯定也会耗应用的内存,所以也慎用。

7.2 复用RecycledViewPool

在TabLayout+ViewPager+RecyclerView的场景中,当多个RecyclerView有相同的item布局结构时,多个RecyclerView共用一个RecycledViewPool可以避免创建ViewHolder的开销,避免GC。RecycledViewPool对象可通过RecyclerView对象获取,也可以自己实现。

RecycledViewPool mPool = mRecyclerView1.getRecycledViewPool();
下一个RecyclerView可直接进行setRecycledViewPool

mRecyclerView2.setRecycledViewPool(mPool);

mRecyclerView3.setRecycledViewPool(mPool);

注意:

(1)RecycledViewPool是依据ItemViewType来索引ViewHolder的,必须确保共享的RecyclerView的Adapter是同一个,或view type 是不会冲突的。

(2)RecycledViewPool可以自主控制需要缓存的ViewHolder数量,每种type的默认容量是5,可通过setMaxRecycledViews来设置大小。mPool.setMaxRecycledViews(itemViewType, number); 但这会增大应用内存开销,所以也需要根据应用具体情况来使用。

(3)利用此特性一般建议设置layout.setRecycleChildrenOnDetach(true);此属性是用来告诉LayoutManager从RecyclerView分离时,是否要回收所有的item,如果项目中复用RecycledViewPool时,开启该功能会更好的实现复用。其他RecyclerView可以复用这些回收的item。

什么时候LayoutManager会从RecyclerView上分离呢,有两种情况:1)重新setLayoutManager()时,比如淘宝页面查看商品列表,可以线性查看,也可以表格形式查看,2)还有一种是RecyclerView从视图树上被remove时。但第一种情况,RecyclerView内部做了回收工作,设不设置影响不大,设置此属性作用主要针对第二种情况。

8、RecyclerView中的一些方法

onViewRecycled():当 ViewHolder 已经确认被回收,且要放进 RecyclerViewPool 中前,该方法会被回调。移出屏幕的ViewHolder会先进入第一级缓存ViewCache中,当第一级缓存空间已满时,会考虑将一级缓存中已有的ViewHolder移到RecyclerViewPool中去。在这个方法中可以考虑图片回收。

onViewAttachedFromWindow(): RecyclerView的item进入屏幕时回调
onViewDetachedFromWindow():RecyclerView的item移出屏幕时回调

onAttachedToRecyclerView() :当 RecyclerView 调用了 setAdapter() 时会触发,新的 adapter 回调 onAttached。
onDetachedFromRecyclerView():当 RecyclerView 调用了 setAdapter() 时会触发,旧的 adapter 回调 onDetached

setHasStableIds()/getItemId():setHasStableIds用来标识每一个itemView是否需要一个唯一标识,当stableId设置为true的时候,每一个itemView数据就有一个唯一标识。getItemId()返回代表这个ViewHolder的唯一标识,如果没有设置stableId唯一性,返回NO_ID=-1。通过setHasStableIds可以使itemView的焦点固定,从而解决RecyclerView的notify方法使得图片加载时闪烁问题。注意:setHasStableIds()必须在 setAdapter() 方法之前调用,否则会抛异常。因为RecyclerView.setAdapter后就设置了观察者,设置了观察者stateIds就不能变了。具体案例可参考:RecyclerView notifyDataSetChanged 导致图片闪烁的真凶

 

9、更多高级用法

9.1 SnapHelper实现卡片效果或ViewPager效果

SnapHelper是一个抽象类,Google 内置了两个默认实现类,LinearSnapHelperPagerSnapHelper

1)LinearSnapHelper可以使RecyclerView 的当前Item 居中显示(横向和竖向都支持)

2)PagerSnapHelper使RecyclerView 像ViewPager一样的效果,每次只能滑动一页(LinearSnapHelper支持快速滑动), PagerSnapHelper也是Item居中对齐。

使用方法如下,想了解更多可参考Android中使用RecyclerView + SnapHelper实现类似ViewPager效果:

 LinearLayoutManager manager = new LinearLayoutManager(getContext());manager.setOrientation(LinearLayoutManager.VERTICAL);mRecyclerView.setLayoutManager(manager);
// 将SnapHelper attach 到RecyclrViewLinearSnapHelper snapHelper = new LinearSnapHelper();snapHelper.attachToRecyclerView(mRecyclerView);

9.2 用SortedList实现添加删除ItemView自动更新

我们在给RecyclerView的ArrayList<Item> data添加一个Data数据时,一般需要自己通知RecyclerView更新,尤其是遇到去重操作,还需要遍历一次data,定位后再决定是插入还是更新现有数据,调用notifyItemInserted(pos),Android Support Lirbrary中提供了一个SortedList工具类,它是一个有序列表,数据变动时会回调SortedList.Callback中方法。

具体使用:

class SortedListAdapter extends RecyclerView.Adapter<TodoViewHolder> {final SortedList<Item> mData;final LayoutInflater mLayoutInflater;public SortedListAdapter(Context context) {mLayoutInflater = LayoutInflater.from(context);mData = new SortedList<Item>(Item.class, new SortedListAdapterCallback<Item>(this){@Overridepublic int compare(Item t0, Item t1) {// 实现这个方法来定义Item的显示顺序int txtComp = t0.mText.compareTo(t1.mText);if (txtComp != 0) {return txtComp;}if (t0.id < t1.id) {return -1;} else if (t0.id > t1.id) {return 1;}return 0;}@Overridepublic boolean areContentsTheSame(Item oldItem,Item newItem) {// 比较两个Item的内容是否一致,如不一致则会调用adapter的notifyItemChanged()return oldItem.mText.equals(newItem.mText);}@Overridepublic boolean areItemsTheSame(Item item1, Item item2) {// 两个Item是不是同一个东西,// 它们的内容或许不一样,但id相同代表就是同一个return item1.id == item2.id;}});}public void addItem(Item item) {mData.add(item);// 会通过SortedListAdapterCallback自动通知更新}...@Overridepublic int getItemCount() {return mData.size();}
}

当数据发生改变时,例如删除,增加等,只需直接对mDataList进行相应操作,无需关心mAdapter内数据显示更新问题,不用再调用notifyDataChanged等函数,因为SortedListAdapterCallback内的回调函数自动完成了。

9.3 详解7.0带来的新工具类:DiffUtil

DiffUtil是support-v7:24.2.0中的新工具类,它用来比较两个数据集,寻找出旧数据集—>新数据集的最小变化量,它和mAdapter.notifyDataSetChanged()最大不同在于它会自动计算新老数据集的差异,并根据差异情况,自动调用以下四个方法:

adapter.notifyItemRangeInserted(position, count);
adapter.notifyItemRangeRemoved(position, count);
adapter.notifyItemMoved(fromPosition, toPosition);
adapter.notifyItemRangeChanged(position, count, payload);

且调用notifyDataSetChanged()不会触发RecyclerView的动画(删除、新增、位移、change动画),其次性能较低,它不管数据是否一样都整个刷新了一遍整个RecyclerView 。

具体使用方法:

DiffUtil.Callback抽象类如下:

    public abstract static class Callback {public abstract int getOldListSize();//老数据集sizepublic abstract int getNewListSize();//新数据集size//新老数据集在同一个position的Item是否是一个对象,如果给itemView设置了stableIds,则仅比较它们单独的id(可能内容不同,如果这里返回true,会调用下面的方法)public abstract boolean areItemsTheSame(int oldItemPosition, int newItemPosition);//这个方法仅仅是上面方法返回true才会调用,判断item的内容是否有变化,类似于Object.equals(Object)public abstract boolean areContentsTheSame(int oldItemPosition, int newItemPosition);//当areItemsTheSame()返回true且areContentsTheSame()返回false,用下面的方法找出两个itemView的data不同之处@Nullablepublic Object getChangePayload(int oldItemPosition, int newItemPosition) {return null;}}

使用时需要实现Callback接口,再将差异结果赋值到我们写的Adapter上。

DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new ProductListDiffCallback(mProducts, newProducts));
diffResult.dispatchUpdatesTo(mProductAdapter);

有一篇外国文章介绍的也很好:DiffUtil使用介绍

9.4 NestedScrollView嵌套RecyclerView

1) 滑动lRecyclerView列表会出现强烈的卡顿感

mRecyclerView.setNestedScrollingEnabled(false);//RecyclerView默认是setNestedScrollingEnabled(true),是支持嵌套滚动的,也就是说当它嵌套在NestedScrollView中时,默认会随着NestedScrollView滚动而滚动,放弃了自己的滚动。将该值置false可以让RecyclerView不支持嵌套滑动,这样RecyclerView可以自己响应滑动事件。

2)每次打开界面都是定位在RecyclerView在屏幕顶端,列表上面的布局都被顶上去了

RecyclerView抢占了焦点,自动滚动导致的.

RecyclerView会在构造方法中调用setFocusableInTouchMode(true), 抢占焦点后一定会定位到第一行的位置,可以在NestedScrollView中添加属性:android:focusableInTouchMode="true",同时在RecyclerView中添加属性:android:descendantFocusability="blocksDescendants"或直接设置mRecyclerVIew.setFocusableInTouchMode(false)

10、别人遇到的问题

10.1 由于RecyclerView缓存view复用导致图片错乱

Recyclerview的缓存机制,作者主要在对RecyclerView的ItemView某些图片进行了属性动画变换,这样就改变了ViewHolder中ImageView的属性,在滑动时,RecyclerView的缓存复用机制可能导致ViewHolder不会重新创建,也不会重新bindView,这样某些ItemView的图片是View属性动画变换后的图片,导致不是自己想要的结果。

10.2 由于RecyclerView关联的GapWorker导致内存泄漏

RecyclerView导致内存泄漏问题分析,其实主要是RecyclerView关联的GapWorker中有一个静态的ThreadLocal对象,静态属性生命周期和应用进程生命周期一致,发生内存泄漏肯定是因为GapWorker的引用链一直关联到Activity中,且没有在相应的时候释放这条引用链。按道理RecyclerView内部onAttachedToWindow和onDetachedFromWindow分别进行了引用和释放引用,是不会发生内存泄漏的,但是由于开发者应对的环境不一样,遇到的坑也不一样。作者这种分析办法还是很值得学习。

后记:

RecyclerView的优化点肯定还有很多,坑也还有很多,这和应用的实际使用情况有很大关系。同时Google开发工程师也一直在优化RecyclerView,我们也要一直学习着。


http://chatgpt.dhexx.cn/article/we3HU95t.shtml

相关文章

大规模WebGL应用引发浏览器崩溃的几种情况及解决办法

一般的Web应用基本上不会导致浏览器崩溃&#xff0c;写Javascript代码也不需要管理内存资源&#xff0c;基本也不需要考虑内存“泄露”的问题。随着H5的崛起&#xff0c;越来越多的原本在桌面端的软件也改头换面迁移到Web上来&#xff0c;比如三维图形类的应用。在Web端显示大规…

浏览器的底层机制、CRP优化技巧、如何解决DOM消耗性能、同步异步、进程和线程

文章目录 浏览器的底层机制&#xff1a;步骤一&#xff1a;生成DOM树「DOM TREE」步骤二&#xff1a;生成CSSOM树「CSSOM TREE」步骤三&#xff1a;合成渲染树 「RENDER TREE」步骤四&#xff1a;Layout布局 & 回流/重排步骤五&#xff1a;分层步骤六&#xff1a;Painting绘…

浏览器页面性能分析指南(chrome)

1.首先我们需要无痕模式打开一个新的chrome标签&#xff0c;可以按CtrlShiftN开启一个无痕模式的chrome 选择无痕模式是为了不让其他的插件干扰你 我们先写一个html的小例子&#xff0c;里面有一些js代码用来做性能分析的用例 html文件的代码如下&#xff1a; 这里是使用vsc…

浏览器兼容性问题,前端性能优化、SEO优化

目录 一、常见浏览器兼容性问题及解决二、前端性能优化三、SEO优化 一、常见浏览器兼容性问题及解决 不同浏览器的内核不尽相同&#xff0c;所以各个浏览器对网页的解析存在一定的差异。 浏览器内核主要分为两种&#xff0c;一是渲染引擎&#xff0c;另一个是js 引擎&#xff…

Chromium浏览器的一些使用总结

Chromium浏览器的一些使用总结 1.快捷键 一般使用快捷键插件实现快捷键的定义、修改、禁用。 关于禁用快捷键插件&#xff0c;在网上找到disable-keyboard-shortcuts插件。正常插件是在google商店上安装的crx格式&#xff0c;国内上不去。有很多第三方插件&#xff0c;考虑到开…

浏览器原理 38 # 加载阶段性能:使用 Audits(Lighthouse) 来优化 Web 性能

说明 浏览器工作原理与实践专栏学习笔记 什么是 Web 性能? Web performance&#xff1a;https://en.wikipedia.org/wiki/Web_performance Web 性能描述了 Web 应用在浏览器上的加载和显示的速度。 性能检测工具&#xff1a;Performance vs Audits Performance 和 Audits&am…

浏览器兼容性 问题产生原因 厂商前缀 滚动条 css hack 渐近增强 和 优雅降级 caniuse

目录 浏览器兼容性问题产生原因厂商前缀滚动条 css hack渐近增强 和 优雅降级caniuse 浏览器兼容性 问题产生原因 市场竞争标准版本的变化 厂商前缀 比如&#xff1a;box-sizing&#xff0c; 谷歌旧版本浏览器中使用-webkit-box-sizing:border-box 市场竞争&#xff0c;标准…

前端性能优化(二)02-页面性能优化之浏览器——浏览器是多进程的 浏览器的渲染机制

前端性能优化&#xff08;二&#xff09;02-页面性能优化之浏览器——浏览器是多进程的 & 浏览器的渲染机制 浏览器是多进程的 进程线程简单的理解&#xff1a;进程里面可以有多个线程&#xff0c;进程就是QQ&#xff0c;线程就是会话。 浏览器是多进程的浏览器之所以能够…

优化-浏览器缓存和压缩优化

一、减少HTTP请求 1.图片地图&#xff1a; 假设导航栏上有五幅图片&#xff0c;点击每张图片都会进入一个链接&#xff0c;这样五张导航的图片在加载时会产生5个HTTP请求。然而&#xff0c;使用一个图片地图可以提高效率&#xff0c;这样就只需要一个HTTP请求。 服务器端图片…

浏览器原理及性能优化

1. 影响页面性能的因素 HTTP 请求复杂的页面逻辑重度的DOM操作服务端响应大量的数据… 2. 优化网页性能 资源压缩与合并&#xff08;代码打包&#xff09;异步加载CDNDNS 预解析缓存… 一、浏览器 1.1 主要作用 浏览器的主要功能就是向服务器发出请求&#xff0c;在浏览器…

前端性能优化(三)——浏览器九大缓存方法

浏览器缓存是浏览器保存数据用于快速读取或避免请求重复资源&#xff0c;提升网页加载速度。缓存的数据到底放哪了呢&#xff1f;作为开发者&#xff0c;有时也需要检查一下缓存中的内容。所以介绍下缓存方法以及缓存内容在哪查找&#xff1f; 上一篇文章介绍的是《浏览器缓存…

chrome浏览器性能分析

匿名模式 匿名模式可以保证Chrome在一个相对干净的环境下运行。比如安装了许多chrome插件&#xff0c;这些插件可能会影响我们分析性能表现 使用快捷键ctrl shift N 即可代码匿名模式下的chrome新标签页 如果想分析移动设备 的页面性能&#xff0c;可用CPU控制器来模拟移动…

浏览器性能优化(初笔记后续修改补充)

参考&#xff1a;【前端工程师面试宝典】学习说明_互联网校招面试真题面经汇总_牛客网 (nowcoder.com) 性能优化 前端性能优化的手段 方面&#xff1a;加载优化、执行优化、渲染优化、样式优化、脚本优化 加载优化:减少HTTP请求、缓存资源、压缩代码、无阻塞、首屏加载、按需…

深入浏览器内部谈性能优化

1. 浏览器发展历史 a. 1995 年&#xff0c;美国网景公司因“网景浏览器”的发布而快速崛起 b. 同年&#xff0c;微软发布windows95&#xff0c;捆绑IE c. 2002年&#xff0c;微软占据了浏览器市场80%的份额 2. 浏览器三大进化路线&#xff08;Web应用能做的事以及未来发展趋…

GreenPlum数据库数据脱敏

1、首先备份要操作的数据库表&#xff0c;防止对原表误操作。 2、例子&#xff1a;数据库表名&#xff1a;st_person&#xff0c;要操作的字段为&#xff1a;phone 3、select phone from st_person ; --看看表里该字段是否有数据&#xff0c;大概格式是什么&#xff0c;该表…

数据库防火墙、数据库加密、数据库脱敏真的可用吗?

数据库是所有信息系统的核心&#xff0c;数据库的安全通常是指其中所存数据的安全&#xff0c;是网络安全、信息安全的重要组成部分。目前有很多相关性产品&#xff0c;如数据库加密、数据库防火墙、数据库脱敏、数据库审计等。 一、数据库防火墙 数据库防火墙系统&#xff1a;…

mysql动态脱敏查询_数据库动态脱敏

原标题&#xff1a;数据库动态脱敏 产品简介 中安威士数据动态脱敏系统(简称VS-DM)&#xff0c;通过截获并修改数据库通讯内容&#xff0c;对数据库中的敏感数据进行在线的屏蔽、变形、字符替换、随机替换等处理&#xff0c;达到对用户访问敏感数据真实内容的权限控制。对存储于…

MySQL 脱敏函数

项目场景&#xff1a; 示例:项目涉及到敏感数据&#xff0c;例如手机号、姓名等使用mysql存储函数解决。 解决方案&#xff1a; 提示&#xff1a;以下主要使用mysql函数CONCAT、LEFT、RIGHT。 1、CONCAT(str1,str2,…) CONCAT()函数返回结果为连接参数产生的字符串。如有任…

跨数据库跨系统,数据脱敏有新招

作者介绍 贝壳找房DBA团队&#xff0c;负责链家、贝壳找房的数据库服务治理及运维&#xff0c;包括MySQL、Redis、Kafka、RocketMQ、TiDB等产品。为保证线上服务高效、安全、稳定运行&#xff0c;面向研发同学提供一站式的数据库操作平台&#xff0c;建设了满足99.99%标准的高可…

imperva数据库脱敏-server2008

首先安装一个server2008其他的server也行 然后安装java环境 后安装tomcat中间件 一路默认就好 这就是tomcat的控制台 然后安装postgresql数据库 官方的要求是9.1-9.3的版本。 这个数据库也是默认安装就好。里面的密码我设的的Webco123 数据库安装完成 下一步安装发现脱敏的控…