一篇博客理解Recyclerview的使用

news2024/11/16 3:51:06

从Android 5.0开始,谷歌公司推出了RecylerView控件,当看到RecylerView这个新控件的时候,大部分人会首先发出一个疑问,recylerview是什么?为什么会有recylerview也就是说recylerview的优点是什么?recylerview怎么用?等等,下面我们将深入解析recylerview。

1.RecyclerView是什么?

RecyclerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能,这一点从它的名字Recyclerview即回收view也可以看出。看到这也许有人会问,不是已经有ListView了吗,为什么还要RecyclerView呢?这就牵扯到第二个问题了。

2.RecyclerView的优点是什么?

根据官方的介绍RecyclerView是ListView的升级版,既然如此那RecyclerView必然有它的优点,现就RecylerView相对于ListView的优点罗列如下: ① RecyclerView封装了viewholder的回收复用,也就是说RecyclerView标准化了ViewHolder,编写Adapter面向的是ViewHolder而不再是View了,复用的逻辑被封装了,写起来更加简单。 ② 提供了一种插拔式的体验,高度的解耦,异常的灵活,针对一个Item的显示RecyclerView专门抽取出了相应的类,来控制Item的显示,使其的扩展性非常强。例如:你想控制横向或者纵向滑动列表效果可以通过LinearLayoutManager这个类来进行控制(与GridView效果对应的是GridLayoutManager,与瀑布流对应的还StaggeredGridLayoutManager等),也就是说RecyclerView不再拘泥于ListView的线性展示方式,它也可以实现GridView的效果等多种效果。你想控制Item的分隔线,可以通过继承RecyclerView的ItemDecoration这个类,然后针对自己的业务需求去抒写代码。 ③ 可以控制Item增删的动画,可以通过ItemAnimator这个类进行控制,当然针对增删的动画,RecyclerView有其自己默认的实现。

recyclerView = (RecyclerView) findViewById(R.id.recyclerView);  
LinearLayoutManager layoutManager = new LinearLayoutManager(this );  
//设置布局管理器  
recyclerView.setLayoutManager(layoutManager);  
//设置为垂直布局,这也是默认的  
layoutManager.setOrientation(OrientationHelper. VERTICAL);  
//设置Adapter  
recyclerView.setAdapter(recycleAdapter);  
 //设置分隔线  
recyclerView.addItemDecoration( new DividerGridItemDecoration(this ));  
//设置增加或删除条目的动画  
recyclerView.setItemAnimator( new DefaultItemAnimator());  

可以看到对RecylerView的设置过程,比ListView要复杂一些,虽然代码抒写上有点复杂,但它的扩展性是极高的。在了解了RecyclerView的一些控制之后,紧接着来看看它的Adapter的写法,RecyclerView的Adapter与ListView的Adapter还是有点区别的,RecyclerView.Adapter,需要实现3个方法: a) onCreateViewHolder() 这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。直接省去了当初的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。

b) onBindViewHolder() 这个方法主要用于适配渲染数据到View中。方法提供给你了一viewHolder而不是原来的convertView。

c) getItemCount() 这个方法就类似于BaseAdapter的getCount方法了,即总共有多少个条目。接下来通过几个小的实例帮助大家更深入的了解RecyclerView的用法。

例子1:用RecyclerView实现一个图片滚动的列表 代码如下:

public class MainActivity extends ActionBarActivity {

	private RecyclerView mRecyclerView;
	private List<Integer> mDatas;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initData();
		// 得到控件
		mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
		// 设置布局管理器
		LinearLayoutManager layoutManager = new LinearLayoutManager(this);
		layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
		mRecyclerView.setLayoutManager(layoutManager);
		// 设置适配器
		mRecyclerView.setAdapter(new MyRecyclerAdapter(this, mDatas));

	}

	private void initData() {
		mDatas = new ArrayList<Integer>(Arrays.asList(R.drawable.kenan1,
				R.drawable.kenan2, R.drawable.kenan3, R.drawable.kenan4,
				R.drawable.kenan5, R.drawable.kenan6, R.drawable.kenan7,
				R.drawable.kenan8));
	}
}
public class DividerItemDecoration extends ItemDecoration {
	
	public DividerItemDecoration() {
		super();
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
			State state) {
		// TODO Auto-generated method stub
		super.getItemOffsets(outRect, view, parent, state);
	}

	@Override
	@Deprecated
	public void onDraw(Canvas c, RecyclerView parent) {
		// TODO Auto-generated method stub
		super.onDraw(c, parent);
	}
	
}
public class MyRecyclerAdapter extends Adapter<MyRecyclerAdapter.MyHolder> {

	private Context mContext;
	private List<Integer> mDatas;

	public MyRecyclerAdapter(Context context, List<Integer> datas) {
		super();
		this.mContext = context;
		this.mDatas = datas;
	}

	@Override
	public int getItemCount() {
		// TODO Auto-generated method stub
		return mDatas.size();
	}

	@Override
	// 填充onCreateViewHolder方法返回的holder中的控件
	public void onBindViewHolder(MyHolder holder, int position) {
		// TODO Auto-generated method stub
		holder.imageView.setImageResource(mDatas.get(position));
	}

	@Override
	// 重写onCreateViewHolder方法,返回一个自定义的ViewHolder
	public MyHolder onCreateViewHolder(ViewGroup arg0, int arg1) {
		// 填充布局
		View view = LayoutInflater.from(mContext).inflate(R.layout.item, null);
		MyHolder holder = new MyHolder(view);
		return holder;
	}

	// 定义内部类继承ViewHolder
	class MyHolder extends ViewHolder {

		private ImageView imageView;

		public MyHolder(View view) {
			super(view);
			imageView = (ImageView) view.findViewById(R.id.iv_item);
		}

	}

	
}

效果如下:

这里写图片描述

这里写图片描述

3.为RecyclerView添加OnItemClickListener回调

效果很不错,这就是RecyclerView的基本用法了,但细心的你会发现,竟然没有提供setOnItemClickListener这个回调,也就是无法响应点击事件,然而在日常开发中,响应点击事件无疑都是必须的,虽然它没有提供,但是我们可以手动添加OnItemClickListener,我们可以在Adapter中添加这个回调接口:

例子2:可以点击的RecyclerView 在原工程基础上对Adapter进行修改,添加OnItemClickListener接口,由于具体点击后的逻辑是交给MainActivity去确定的,所以我们定义抽象的OnItemClickListener接口,里面有一个抽象方法,用于设置被点击后的逻辑:

//item的回调接口
	public interface OnItemClickListener{
		void onItemClick(View view,int Position);
	}

对外暴露一个设置点击监听器的方法,其中传入需要OnItemClickListener接口

//定义一个设置点击监听器的方法
	public void setOnItemClickListener(OnItemClickListener itemClickListener) {
		this.mItemClickListener = itemClickListener;
	}

在绑定ViewHolder的逻辑之中,对RecyclerView的每一个itemView设置点击事件:

@Override
	// 填充onCreateViewHolder方法返回的holder中的控件
	public void onBindViewHolder(final MyHolder holder, final int position) {
		// TODO Auto-generated method stub
		holder.imageView.setImageResource(mDatas.get(position));
		//如果设置了回调,则设置点击事件  
		if(mItemClickListener != null){
			holder.itemView.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					mItemClickListener.onItemClick(holder.itemView, position);
					
				}
			});
		}
	}

最后粘上Adapter的全部代码,其他代码均和例子1一样

public class MyRecyclerAdapter extends Adapter<MyRecyclerAdapter.MyHolder> {

	private Context mContext;
	private List<Integer> mDatas;
	private OnItemClickListener mItemClickListener;

	public MyRecyclerAdapter(Context context, List<Integer> datas) {
		super();
		this.mContext = context;
		this.mDatas = datas;
	}
	//item的回调接口
	public interface OnItemClickListener{
		void onItemClick(View view,int Position);
	}
	//定义一个设置点击监听器的方法
	public void setOnItemClickListener(OnItemClickListener itemClickListener) {
		this.mItemClickListener = itemClickListener;
	}
	@Override
	public int getItemCount() {
		// TODO Auto-generated method stub
		return mDatas.size();
	}

	@Override
	// 填充onCreateViewHolder方法返回的holder中的控件
	public void onBindViewHolder(final MyHolder holder, final int position) {
		// TODO Auto-generated method stub
		holder.imageView.setImageResource(mDatas.get(position));
		//如果设置了回调,则设置点击事件  
		if(mItemClickListener != null){
			holder.itemView.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					mItemClickListener.onItemClick(holder.itemView, position);
					
				}
			});
		}
	}

	@Override
	// 重写onCreateViewHolder方法,返回一个自定义的ViewHolder
	public MyHolder onCreateViewHolder(ViewGroup viewgroup, int i) {
		// 填充布局
		View view = LayoutInflater.from(mContext).inflate(R.layout.item, null);
		MyHolder holder = new MyHolder(view);
		return holder;
	}

	// 定义内部类继承ViewHolder
	class MyHolder extends ViewHolder {

		private ImageView imageView;

		public MyHolder(View view) {
			super(view);
			imageView = (ImageView) view.findViewById(R.id.iv_item);
		}

	}

	
}

效果如下:

这里写图片描述

4.自定义RecyclerView实现滚动时内容联动

例子3:RecyclerView制作相册效果 效果:在原工程的基础上进行修改,改成相册效果,即上面显示一张大图,下面的RecyclerView做为图片切换的指示器。

首先修改下布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.recyclerviewdemo.MainActivity" >

    <ImageView
        android:id="@+id/iv_group"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_margin="10dp"
        android:layout_weight="1"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_launcher" />

    <!--
    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >

        <ImageView
            android:id="@+id/iv_group"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_gravity="center"
            android:layout_margin="10dp"
            android:scaleType="centerCrop"
            android:src="@drawable/ic_launcher" />
    </FrameLayout>
    -->

    <com.example.recyclerviewdemo.MyRecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_centerVertical="true"
        android:layout_gravity="bottom" />

</LinearLayout>

添加一个显示大图的区域,把RecyclerView改为自己定义的。 然后看我们自定义RecyclerView的代码:

public class MyRecyclerView extends RecyclerView {

    private onItemScrollChangeListener mItemScrollChangeListener;
    private View mCurrentView;

    public MyRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    // 回调的接口
    public interface onItemScrollChangeListener {
        void onChange(View view, int position);
    }

    // 对外暴露设置滚动接口的方法
    public void setOnItemScrollChangeListener(
            onItemScrollChangeListener itemScrollChangeListener) {
        this.mItemScrollChangeListener = itemScrollChangeListener;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // TODO Auto-generated method stub
        super.onLayout(changed, l, t, r, b);
        mCurrentView = getChildAt(0);
        if (mItemScrollChangeListener != null) {
            mItemScrollChangeListener.onChange(mCurrentView,
                    getChildPosition(mCurrentView));
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        // TODO Auto-generated method stub

        if (e.getAction() == MotionEvent.ACTION_MOVE) {
            mCurrentView = getChildAt(0);
            if (mItemScrollChangeListener != null) {
                mItemScrollChangeListener.onChange(mCurrentView,
                        getChildPosition(mCurrentView));
            }
        }
        return super.onTouchEvent(e);
    }
}

最主要是重写onLayout,onTouchEvent方法,并设置滚动监听的回调,还有向外界暴露监听器的逻辑。

然后是Adapter的代码

public class MyRecyclerAdapter extends Adapter<MyRecyclerAdapter.MyHolder> {

	private Context mContext;
	private List<Integer> mDatas;
	//private OnItemClickListener mItemClickListener;

	public MyRecyclerAdapter(Context context, List<Integer> datas) {
		super();
		this.mContext = context;
		this.mDatas = datas;
	}
	/*//item的回调接口
	public interface OnItemClickListener{
		void onItemClick(View view,int Position);
	}
	//定义一个设置点击监听器的方法
	public void setOnItemClickListener(OnItemClickListener itemClickListener) {
		this.mItemClickListener = itemClickListener;
	}*/
	@Override
	public int getItemCount() {
		// TODO Auto-generated method stub
		return mDatas.size();
	}

	@Override
	// 填充onCreateViewHolder方法返回的holder中的控件
	public void onBindViewHolder(final MyHolder holder, final int position) {
		// TODO Auto-generated method stub
		holder.imageView.setImageResource(mDatas.get(position));
		/*//如果设置了回调,则设置点击事件  
		if(mItemClickListener != null){
			holder.itemView.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					mItemClickListener.onItemClick(holder.itemView, position);
					
				}
			});
		}*/
	}

	@Override
	// 重写onCreateViewHolder方法,返回一个自定义的ViewHolder
	public MyHolder onCreateViewHolder(ViewGroup viewgroup, int i) {
		// 填充布局
		View view = LayoutInflater.from(mContext).inflate(R.layout.item, null);
		MyHolder holder = new MyHolder(view);
		return holder;
	}

	// 定义内部类继承ViewHolder
	class MyHolder extends ViewHolder {

		private ImageView imageView;

		public MyHolder(View view) {
			super(view);
			imageView = (ImageView) view.findViewById(R.id.iv_item);
		}

	}

	
}

定义了一个滚动时回调的接口,然后在onTouchEvent中,监听ACTION_MOVE,用户手指滑动时,不断把当前第一个View回调回去 关于为什么getChildAt(0)和getChildPosition()可用,起初我以为有getFirstVisibleItem这个方法,后来发现么有;但是发现了getRecycledViewPool()看名字我觉得是Viewholder那个缓存队列,我想那么直接取这个队列的第一个不就是我要的View么,后来没有成功。我就观察它内部的View,最后发现,第一个显示的始终是它第一个child,至于getChildPosition这个看方法就看出来了。 效果如下:

这里写图片描述

5.RecyclerView实现瀑布流

例子4:用RecyclerView打造瀑布流效果 其中大部分内容实现和基本的RecyclerView使用是一样的,就不多叙述了,就一个地方不同,就是我们在适配器中绑定ViewHolder的方法中需要重新给我们的itemView布局设置height,这里是生成随机数来设置高度的。

//得到随机item的高度
	private void getRandomHeight(List<Integer> datas) {
		heights = new ArrayList<Integer>();
		for (int i = 0; i < datas.size(); i++) {
			heights.add((int) (200+Math.random()*100));
		}
	}

在onBindViewHolder方法中:

@Override
	// 填充onCreateViewHolder方法返回的holder中的控件
	public void onBindViewHolder(final MyHolder holder, int position) {
		// TODO Auto-generated method stub	
		//得到item的LayoutParams布局参数
		ViewGroup.LayoutParams params= holder.itemView.getLayoutParams();
		//把随机的高度赋予item布局
		params.height = heights.get(position);
		//把params设置给item布局
		holder.itemView.setLayoutParams(params);
		//为控件绑定数据
		holder.imageView.setImageResource(mDatas.get(position));
		//如果设置了监听那么它就不为空,然后回调相应的方法
		if(onItemClickListener!=null){
			holder.itemView.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					//得到当前点击item的位置pos
					int position = holder.getLayoutPosition();
					//把事件交给我们实现的接口那里处理
					onItemClickListener.onOnItemClick(holder.itemView, position);
				}
			});
			holder.itemView.setOnLongClickListener(new OnLongClickListener() {
				
				@Override
				public boolean onLongClick(View v) {
					//得到当前点击item的位置pos
					int position = holder.getLayoutPosition();
					//把事件交给我们实现的接口那里处理
					onItemClickListener.onOnItemClick(holder.itemView, position);
					return true;
				}
			});
		}
	}

最后附上项目完整代码:

public class MainActivity extends ActionBarActivity {

	private RecyclerView mRecyclerView;
	private List<Integer> mDatas;
	private MyRecyclerAdapter adapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initData();
		// 得到控件
		mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
		mRecyclerView.setItemAnimator(new DefaultItemAnimator());
		//设置RecyclerView布局管理器为2列垂直排布
		StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
		mRecyclerView.setLayoutManager(layoutManager);
		
		adapter = new MyRecyclerAdapter(this, mDatas);
		mRecyclerView.setAdapter(adapter);
		adapter.setOnItemClickListener(new onItemClickListener() {
			
			@Override
			public void onOnItemClick(View view, int position) {
				// TODO Auto-generated method stub
				Toast.makeText(MainActivity.this, "点击了:"+position, Toast.LENGTH_SHORT).show();
			}
			
			@Override
			public void onLongClick(View view, int position) {
				 //长按删除
				mDatas.remove(position);
				adapter.notifyItemRemoved(position);
			}
		});

	}
	
	private void initData() {
		mDatas = new ArrayList<Integer>(Arrays.asList(R.drawable.kenan1,
				R.drawable.kenan2, R.drawable.kenan3, R.drawable.kenan4,
				R.drawable.kenan5, R.drawable.kenan6, R.drawable.kenan7,
				R.drawable.kenan8,R.drawable.kenan1,
				R.drawable.kenan2, R.drawable.kenan3, R.drawable.kenan4));
	}
}
public class MyRecyclerAdapter extends Adapter<MyRecyclerAdapter.MyHolder> {

	private Context mContext;
	private List<Integer> mDatas;
	private List<Integer> heights;
	private onItemClickListener onItemClickListener;
	public MyRecyclerAdapter(Context context, List<Integer> datas) {
		super();
		this.mContext = context;
		this.mDatas = datas;
		getRandomHeight(this.mDatas);
	}
	
	public interface onItemClickListener{
		//条目被点击时触发的回调
		void onOnItemClick(View view,int position);
		//长按时触发的回调
		void onLongClick(View view,int position);
	}
	
	
	public void setOnItemClickListener(onItemClickListener onItemClickListener) {
		this.onItemClickListener = onItemClickListener;
	}
	@Override
	public int getItemCount() {
		// TODO Auto-generated method stub
		return mDatas.size();
	}

	@Override
	// 填充onCreateViewHolder方法返回的holder中的控件
	public void onBindViewHolder(final MyHolder holder, int position) {
		// TODO Auto-generated method stub	
		//得到item的LayoutParams布局参数
		ViewGroup.LayoutParams params= holder.itemView.getLayoutParams();
		//把随机的高度赋予item布局
		params.height = heights.get(position);
		//把params设置给item布局
		holder.itemView.setLayoutParams(params);
		//为控件绑定数据
		holder.imageView.setImageResource(mDatas.get(position));
		//如果设置了监听那么它就不为空,然后回调相应的方法
		if(onItemClickListener!=null){
			holder.itemView.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					//得到当前点击item的位置pos
					int position = holder.getLayoutPosition();
					//把事件交给我们实现的接口那里处理
					onItemClickListener.onOnItemClick(holder.itemView, position);
				}
			});
			holder.itemView.setOnLongClickListener(new OnLongClickListener() {
				
				@Override
				public boolean onLongClick(View v) {
					//得到当前点击item的位置pos
					int position = holder.getLayoutPosition();
					//把事件交给我们实现的接口那里处理
					onItemClickListener.onOnItemClick(holder.itemView, position);
					return true;
				}
			});
		}
	}

	@Override
	// 重写onCreateViewHolder方法,返回一个自定义的ViewHolder
	public MyHolder onCreateViewHolder(ViewGroup viewGroup, int arg1) {
		// 填充布局
		View view = LayoutInflater.from(mContext).inflate(R.layout.item,viewGroup, false);
		MyHolder holder = new MyHolder(view);
		return holder;
	}

	// 定义内部类继承ViewHolder
	class MyHolder extends ViewHolder {

		private ImageView imageView;
		public MyHolder(View view) {
			super(view);
			imageView = (ImageView) view.findViewById(R.id.iv_item);
		}

	}
	//得到随机item的高度
	private void getRandomHeight(List<Integer> datas) {
		heights = new ArrayList<Integer>();
		for (int i = 0; i < datas.size(); i++) {
			heights.add((int) (200+Math.random()*100));
		}
	}
}

更多Android进阶指南 可以扫码 解锁 《Android十大板块文档》

1.Android车载应用开发系统学习指南(附项目实战)

2.Android Framework学习指南,助力成为系统级开发高手

3.2023最新Android中高级面试题汇总+解析,告别零offer

4.企业级Android音视频开发学习路线+项目实战(附源码)

5.Android Jetpack从入门到精通,构建高质量UI界面

6.Flutter技术解析与实战,跨平台首要之选

7.Kotlin从入门到实战,全方面提升架构基础

8.高级Android插件化与组件化(含实战教程和源码)

9.Android 性能优化实战+360°全方面性能调优

10.Android零基础入门到精通,高手进阶之路

敲代码不易,关注一下吧。ღ( ´・ᴗ・` ) 🤔

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

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

相关文章

图像视觉特效处理工具:Boris FX Optics 2024.0.1

BorisFX光效插件Optics首发2024版&#xff1a;3大新功能详解 2023年9月15日&#xff0c;全球领先的视觉后期软件开发公司BorisFX推出了旗下知名软件Boris FX Optics的全新2024版本&#xff0c;这款备受后期处理爱好者喜爱的Photoshop插件和独立程序再次升级&#xff0c;为您的…

【PC】特殊空投-2023年10月

亲爱的玩家朋友们&#xff0c;大家好&#xff01; 10月特殊空投活动来袭。本月我们也准备了超多活动等着大家来体验。快来完成任务获得丰富的奖励吧&#xff01;签到活动&#xff0c;每周一次的PUBG空投节&#xff0c;还有可以领取PGC2023免费投票劵的活动等着大家&#xff01;…

聊聊统一认证中的四种安全认证协议(干货分享)

大家好&#xff0c;我是陈哈哈。单点登录SSO的出现是为了解决众多企业面临的痛点&#xff0c;场景即用户需要登录N个程序或系统&#xff0c;每个程序与系统都有不同的用户名和密码。在企业发展初期&#xff0c;可能仅仅有几个程序时&#xff0c;管理账户和密码不是一件难事。但…

软考系统架构师知识点集锦九:数据库系统

一、考情分析 二、考点精讲 2.1数据库概述 2.1.1数据库模式 (1)三级模式:外模式对应视图&#xff0c;模式(也称为概念模式)对应数据库表&#xff0c;内模式对应物理文件。(2)两层映像:外模式-模式映像&#xff0c;模式-内模式映像;两层映像可以保证数据库中的数据具有较高的…

linux查看系统版本、内核信息、操作系统类型版本

1. 使用 uname 命令&#xff1a;这将显示完整的内核版本信息&#xff0c;包括内核版本号、主机名、操作系统类型等。 uname -a2. 使用 lsb_release 命令&#xff08;仅适用于支持 LSB&#xff08;Linux Standard Base&#xff09;的发行版&#xff09;&#xff1a;这将显示包含…

reactos 可调试光盘映像

链接&#xff1a;https://pan.baidu.com/s/13M9BZN4IDrWLc3bjnHO79g?pwd0gst 提取码&#xff1a;0gst

【计算机网络笔记】传输层——多路复用和多路分用

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

08 _ 栈:如何实现浏览器的前进和后退功能?

浏览器的前进、后退功能,我想你肯定很熟悉吧? 当你依次访问完一串页面a-b-c之后,点击浏览器的后退按钮,就可以查看之前浏览过的页面b和a。当你后退到页面a,点击前进按钮,就可以重新查看页面b和c。但是,如果你后退到页面b后,点击了新的页面d,那就无法再通过前进、后退…

Qwt QwtScaleDraw自定义坐标轴

1.概述 QwtScaleDraw 是 Qt 绘图库 Qwt 中的一个类&#xff0c;用于绘制坐标轴刻度线和刻度标签。它提供了一些方法和属性来设置刻度线和标签的样式、布局和对齐方式。 以下是类继承关系&#xff1a; 2.常用方法 标签相关方法&#xff1a; setLabelRotation(double angle)&…

Hudi系列文章7-RFC24 Flink 写入流程优化

文章目录 前言问题背景瓶颈与解决方案瓶颈一解决方法工作流程&#xff1a;精准一次语义容灾CoorinatorCheckpoint如何配合使用StreamWriteOperatorCoordinator CheckpointedFunctionStreamWriteFunctionInstant 提前生成问题 瓶颈二问题解决方案BucketAssignerBucketWriter 重点…

将字符串中符合规则的元素替换为指定元素 re.sub()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 将字符串中符合规则的元素 替换为指定元素 re.sub() 选择题 请问re.sub(r[0-9],*,s)的结果是&#xff1a; import re s "hello123" print("【显示】s ",s) print(&quo…

采购申请单明细账/汇总账页面编写

业务需求和功能 1、功能&#xff1a;编写采购申请页面和采购申请管理页面。在申请单界面添加常用的查询条件&#xff0c;如单品、申请单等。在采购申请管理页面以单品维度去展示采购申请单的汇总信息&#xff0c;添加一个默认查询时间为7天&#xff0c;并对查询出来的不同状态…

【设计模式三原则】

设计模式三原则 单一职责原则开放封闭原则依赖倒转原则里氏代换原则 我们在进行程序设计的时候&#xff0c;要尽可能地保证程序的可扩展性、可维护性和可读性&#xff0c;所以需要使用一些设计模式&#xff0c;这些设计模式都遵循了以下三个原则&#xff0c;下面来依次为大家介…

目标检测算法-SSD

1. SSD介绍 计算机确定图像中一个物体的位置需要四个参数&#xff1a;中心点的x轴、y轴坐标、框的高和宽。 当一张图片被传入SSD的网络中时&#xff0c;图片首先会被调整为300*300的大小。为了防止失真&#xff0c;其会在图片的边缘加上灰条。 之后SSD会将这种图片分为六种不…

IR2104/IR2184电机方案选择

供电越大Rdson越小 D3要用快恢复或者超快恢复不要用肖特基 上图有自举电容的取值公式&#xff0c;自举电容不能用电解电容&#xff0c;最好使用C0G因为它在不停的充放电 C31必须大于10倍C28

基于探路者算法的无人机航迹规划-附代码

基于探路者算法的无人机航迹规划 文章目录 基于探路者算法的无人机航迹规划1.探路者搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用探路者算法来优化无人机航迹规划。 1.探路者…

LeetCode 2742.给墙壁刷油漆

思路 dp(u,count)为当前再考虑下标为1-u的墙面&#xff0c;并且还有count免费工次的最小代价 主要是递归边界的选择&#xff1a; u1<count return 0; if(u-1&&count<0)return 0x3f3f3f3f; if(u-1&&count0)retrun 0; 这三个可以合并成 if(u<count) …

k8s基本操作命令

目录 1、//查看资源对象简写 2、//查看集群信息 3、//配置kubectl自动补全 4、//node节点查看日志 5、//查看 master 节点状态 6、//查看命令空间 7、//查看default命名空间的所有资源 8、//创建命名空间app 9、//删除命名空间app 10、//在命名空间kube-public 创建…

量子计算与量子密码(入门级-少图版)

量子计算与量子密码 写在最前面一些可能带来的有趣的知识和潜在的收获 1、Introduction导言四个特性不确定性&#xff08;自由意志论&#xff09;Indeterminism不确定性Uncertainty叠加原理(线性)superposition (linearity)纠缠entanglement 虚数的常见基本运算欧拉公式&#x…

指针运算笔试题解析(2)

指针运算笔试题解析 题目一解析 题目二解析 压轴题&#xff08;困难&#xff09;解析 题目一 #include <stdio.h> int main() {int aa[2][5] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int *ptr1 (int *)(&aa 1);int *ptr2 (int *)(*(aa 1));printf( "%d&#x…