03.视频播放器Api说明
03.视频播放器Api说明
目录介绍
- 01.最简单的播放
- 02.如何切换视频内核
- 03.切换视频模式
- 04.切换视频清晰度
- 05.视频播放监听
- 06.列表中播放处理
- 07.悬浮窗口播放
- 08.其他重要功能Api
- 09.播放多个视频
- 10.VideoPlayer相关Api
- 11.Controller相关Api
- 12.边播放边缓存api
- 13.类似抖音视频预加载
- 14.视频播放器埋点
00.视频播放器通用框架
- 基础封装视频播放器player,可以在ExoPlayer、MediaPlayer,声网RTC视频播放器内核,原生MediaPlayer可以自由切换
- 对于视图状态切换和后期维护拓展,避免功能和业务出现耦合。比如需要支持播放器UI高度定制,而不是该lib库中UI代码
- 针对视频播放,音频播放,播放回放,以及视频直播的功能。使用简单,代码拓展性强,封装性好,主要是和业务彻底解耦,暴露接口监听给开发者处理业务具体逻辑
- 该播放器整体架构:播放器内核(自由切换) + 视频播放器 + 边播边缓存 + 高度定制播放器UI视图层
- 项目地址:github.com/yangchong21…
- 关于视频播放器整体功能介绍文档:juejin.im/post/688345…
01.最简单的播放
- 必须需要的四步骤代码如下所示
//创建基础视频播放器,一般播放器的功能
BasisVideoController controller = new BasisVideoController(this);
//设置控制器
mVideoPlayer.setVideoController(controller);
//设置视频播放链接地址
mVideoPlayer.setUrl(url);
//开始播放
mVideoPlayer.start();
复制代码 - 开始播放
//播放视频
videoPlayer.start();
复制代码
02.如何切换视频内核
- 创建视频播放器
PlayerFactory playerFactory = IjkPlayerFactory.create();
IjkVideoPlayer ijkVideoPlayer = (IjkVideoPlayer) playerFactory.createPlayer(this);
PlayerFactory playerFactory = ExoPlayerFactory.create();
ExoMediaPlayer exoMediaPlayer = (ExoMediaPlayer) playerFactory.createPlayer(this);
PlayerFactory playerFactory = MediaPlayerFactory.create();
AndroidMediaPlayer androidMediaPlayer = (AndroidMediaPlayer) playerFactory.createPlayer(this);
复制代码 - 如何配置视频内核
//播放器配置,注意:此为全局配置,例如下面就是配置ijk内核播放器
VideoViewManager.setConfig(VideoPlayerConfig.newBuilder()
.setLogEnabled(true)//调试的时候请打开日志,方便排错
.setPlayerFactory(IjkPlayerFactory.create())
.build());
复制代码 - 切换视频内核处理代码
@SuppressLint("SetTextI18n")
private void setChangeVideoType(@ConstantKeys.PlayerType int type){
//切换播放核心,不推荐这么做,我这么写只是为了方便测试
VideoPlayerConfig config = VideoViewManager.getConfig();
try {
Field mPlayerFactoryField = config.getClass().getDeclaredField("mPlayerFactory");
mPlayerFactoryField.setAccessible(true);
PlayerFactory playerFactory = null;
switch (type) {
case ConstantKeys.VideoPlayerType.TYPE_IJK:
playerFactory = IjkPlayerFactory.create();
mTvTitle.setText("视频内核:" + " (IjkPlayer)");
break;
case ConstantKeys.VideoPlayerType.TYPE_EXO:
playerFactory = ExoPlayerFactory.create();
mTvTitle.setText("视频内核:" + " (ExoPlayer)");
break;
case ConstantKeys.VideoPlayerType.TYPE_NATIVE:
playerFactory = MediaPlayerFactory.create();
mTvTitle.setText("视频内核:" + " (MediaPlayer)");
break;
case ConstantKeys.VideoPlayerType.TYPE_RTC:
break;
}
mPlayerFactoryField.set(config, playerFactory);
} catch (Exception e) {
e.printStackTrace();
}
}
复制代码
03.切换视频模式
- 关于全屏模式相关api
//进入全屏
mVideoPlayer.startFullScreen();
//退出全屏
mVideoPlayer.stopFullScreen();
复制代码 - 关于小窗口播放相关api
//开启小屏
mVideoPlayer.startTinyScreen();
//退出小屏
mVideoPlayer.stopTinyScreen();
复制代码
04.切换视频清晰度
05.视频播放监听
- 这个分为两部分:第一部分是播放模式监听,第二部分是播放状态监听,暴露给开发者。这里不建议使用0,1,非常不方便简明之意,采用注解限定。
mVideoPlayer.setOnStateChangeListener(new OnVideoStateListener() {
/**
* 播放模式
* 普通模式,小窗口模式,正常模式三种其中一种
* MODE_NORMAL 普通模式
* MODE_FULL_SCREEN 全屏模式
* MODE_TINY_WINDOW 小屏模式
* @param playerState 播放模式
*/
@Override
public void onPlayerStateChanged(int playerState) {
switch (playerState) {
case ConstantKeys.PlayMode.MODE_NORMAL:
//普通模式
break;
case ConstantKeys.PlayMode.MODE_FULL_SCREEN:
//全屏模式
break;
case ConstantKeys.PlayMode.MODE_TINY_WINDOW:
//小屏模式
break;
}
} /**
* 播放状态
* -1 播放错误
* 0 播放未开始
* 1 播放准备中
* 2 播放准备就绪
* 3 正在播放
* 4 暂停播放
* 5 正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放)
* 6 暂停缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停
* 7 播放完成
* 8 开始播放中止
* @param playState 播放状态,主要是指播放器的各种状态
*/
@Override
public void onPlayStateChanged(int playState) {
switch (playState) {
case ConstantKeys.CurrentState.STATE_IDLE:
//播放未开始,初始化
break;
case ConstantKeys.CurrentState.STATE_START_ABORT:
//开始播放中止
break;
case ConstantKeys.CurrentState.STATE_PREPARING:
//播放准备中
break;
case ConstantKeys.CurrentState.STATE_PREPARED:
//播放准备就绪
break;
case ConstantKeys.CurrentState.STATE_ERROR:
//播放错误
break;
case ConstantKeys.CurrentState.STATE_BUFFERING_PLAYING:
//正在缓冲
break;
case ConstantKeys.CurrentState.STATE_PLAYING:
//正在播放
break;
case ConstantKeys.CurrentState.STATE_PAUSED:
//暂停播放
break;
case ConstantKeys.CurrentState.STATE_BUFFERING_PAUSED:
//暂停缓冲
break;
case ConstantKeys.CurrentState.STATE_COMPLETED:
//播放完成
break;
}
}
});
复制代码
06.在列表中播放
- 第一步:初始化视频播放器,创建VideoPlayer对象
mVideoView = new VideoPlayer(context);
mVideoView.setOnStateChangeListener(new VideoPlayer.SimpleOnStateChangeListener() {
@Override
public void onPlayStateChanged(int playState) {
//监听VideoViewManager释放,重置状态
if (playState == ConstantKeys.CurrentState.STATE_IDLE) {
PlayerUtils.removeViewFormParent(mVideoView);
mLastPos = mCurPos;
mCurPos = -1;
}
}
});
mController = new BasisVideoController(context);
mVideoView.setController(mController);
复制代码 - 第二步:设置RecyclerView和Adapter
mAdapter.setOnItemChildClickListener(new OnItemChildClickListener() {
@Override
public void onItemChildClick(int position) {
//点击item播放视频
startPlay(position);
}
});
mRecyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
@Override
public void onChildViewAttachedToWindow(@NonNull View view) { } @Override
public void onChildViewDetachedFromWindow(@NonNull View view) {
FrameLayout playerContainer = view.findViewById(R.id.player_container);
View v = playerContainer.getChildAt(0);
if (v != null && v == mVideoView && !mVideoView.isFullScreen()) {
//销毁视频
releaseVideoView();
}
}
});
复制代码 - 第三步:播放视频和销毁视频的逻辑代码
/**
* 开始播放
* @param position 列表位置
*/
protected void startPlay(int position) {
if (mCurPos == position) return;
if (mCurPos != -1) {
releaseVideoView();
}
VideoInfoBean videoBean = mVideos.get(position);
mVideoView.setUrl(videoBean.getVideoUrl());
View itemView = mLinearLayoutManager.findViewByPosition(position);
if (itemView == null) return;
VideoRecyclerViewAdapter.VideoHolder viewHolder = (VideoRecyclerViewAdapter.VideoHolder) itemView.getTag();
//把列表中预置的PrepareView添加到控制器中,注意isPrivate此处只能为true。
mController.addControlComponent(viewHolder.mPrepareView, true);
PlayerUtils.removeViewFormParent(mVideoView);
viewHolder.mPlayerContainer.addView(mVideoView, 0);
//播放之前将VideoView添加到VideoViewManager以便在别的页面也能操作它
VideoViewManager.instance().add(mVideoView, "list");
mVideoView.start();
mCurPos = position;
} private void releaseVideoView() {
mVideoView.release();
if (mVideoView.isFullScreen()) {
mVideoView.stopFullScreen();
}
if(getActivity().getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
mCurPos = -1;
}
复制代码
08.其他重要功能Api
- 设置视频播放器背景图,和视频标题。
//注意,下面这个controller是指BasisVideoController
//设置视频背景图
ImageView thumb = controller.getThumb();
Glide.with(this).load(R.drawable.image_default).into(controller.getThumb());
//设置视频标题
controller.setTitle("视频标题");
复制代码 - 判断是否锁屏
//判断是否锁屏
boolean locked = controller.isLocked();
//设置是否锁屏
controller.setLocked(true);
复制代码 - 设置播放视频缩放类型。借鉴于网络博客,类似图片缩放。建议选择16:9类型,最常见
mVideoPlayer.setScreenScaleType(ConstantKeys.PlayerScreenScaleType.SCREEN_SCALE_16_9);
mVideoPlayer.setScreenScaleType(ConstantKeys.PlayerScreenScaleType.SCREEN_SCALE_DEFAULT);
mVideoPlayer.setScreenScaleType(ConstantKeys.PlayerScreenScaleType.SCREEN_SCALE_4_3);
mVideoPlayer.setScreenScaleType(ConstantKeys.PlayerScreenScaleType.SCREEN_SCALE_MATCH_PARENT);
mVideoPlayer.setScreenScaleType(ConstantKeys.PlayerScreenScaleType.SCREEN_SCALE_ORIGINAL);
mVideoPlayer.setScreenScaleType(ConstantKeys.PlayerScreenScaleType.SCREEN_SCALE_CENTER_CROP);
复制代码
09.播放多个视频
- 这个举一个例子,比如同时播放两个视频,当然这种情况在app中可能比较少
//必须设置
player1.setUrl(VOD_URL_1);
VideoPlayerBuilder.Builder builder = VideoPlayerBuilder.newBuilder();
builder.setEnableAudioFocus(false);
VideoPlayerBuilder videoPlayerBuilder = new VideoPlayerBuilder(builder);
player1.setVideoBuilder(videoPlayerBuilder);
BasisVideoController controller1 = new BasisVideoController(this);
player1.setController(controller1);
mVideoViews.add(player1); //必须设置
player2.setUrl(VOD_URL_2);
VideoPlayerBuilder.Builder builder2 = VideoPlayerBuilder.newBuilder();
builder.setEnableAudioFocus(false);
VideoPlayerBuilder videoPlayerBuilder2 = new VideoPlayerBuilder(builder2);
player2.setVideoBuilder(videoPlayerBuilder2);
BasisVideoController controller2 = new BasisVideoController(this);
player2.setController(controller2);
mVideoViews.add(player2);
复制代码 - 那么要是页面切换到后台,如何处理多个视频的暂停功能呢?如下所示:
@Override
protected void onPause() {
super.onPause();
for (VideoPlayer vv : mVideoViews) {
vv.pause();
}
} @Override
protected void onResume() {
super.onResume();
for (VideoPlayer vv : mVideoViews) {
vv.pause();
}
} @Override
protected void onDestroy() {
super.onDestroy();
for (VideoPlayer vv : mVideoViews) {
vv.release();
}
} @Override
public void onBackPressed() {
for (VideoPlayer vv : mVideoViews) {
if (vv.onBackPressed())
return;
}
super.onBackPressed();
}
复制代码
10.VideoPlayer相关Api
- 关于视频播放相关的api如下所示
//暂停播放
mVideoPlayer.pause();
//视频缓冲完毕,准备开始播放时回调
mVideoPlayer.onPrepared();
//重新播放
mVideoPlayer.replay(true);
//继续播放
mVideoPlayer.resume();
//调整播放进度
mVideoPlayer.seekTo(100);
//循环播放, 默认不循环播放
mVideoPlayer.setLooping(true);
//设置播放速度
mVideoPlayer.setSpeed(1.1f);
//设置音量 0.0f-1.0f 之间
mVideoPlayer.setVolume(1,1);
//开始播放
mVideoPlayer.start();
复制代码 - 关于视频切换播放模式相关api
//判断是否处于全屏状态
boolean fullScreen = mVideoPlayer.isFullScreen();
//是否是小窗口模式
boolean tinyScreen = mVideoPlayer.isTinyScreen();
//进入全屏
mVideoPlayer.startFullScreen();
//退出全屏
mVideoPlayer.stopFullScreen();
//开启小屏
mVideoPlayer.startTinyScreen();
//退出小屏
mVideoPlayer.stopTinyScreen();
复制代码 - 关于其他比如获取速度,音量,设置属性相关Api
//VideoPlayer相关
VideoPlayerBuilder.Builder builder = VideoPlayerBuilder.newBuilder();
VideoPlayerBuilder videoPlayerBuilder = new VideoPlayerBuilder(builder);
//设置视频播放器的背景色
builder.setPlayerBackgroundColor(Color.BLACK);
//设置小屏的宽高
int[] mTinyScreenSize = {0, 0};
builder.setTinyScreenSize(mTinyScreenSize);
//是否开启AudioFocus监听, 默认开启
builder.setEnableAudioFocus(false);
mVideoPlayer.setVideoBuilder(videoPlayerBuilder);
//截图
Bitmap bitmap = mVideoPlayer.doScreenShot();
//移除所有播放状态监听
mVideoPlayer.clearOnStateChangeListeners();
//获取当前缓冲百分比
int bufferedPercentage = mVideoPlayer.getBufferedPercentage();
//获取当前播放器的状态
int currentPlayerState = mVideoPlayer.getCurrentPlayerState();
//获取当前的播放状态
int currentPlayState = mVideoPlayer.getCurrentPlayState();
//获取当前播放的位置
long currentPosition = mVideoPlayer.getCurrentPosition();
//获取视频总时长
long duration = mVideoPlayer.getDuration();
//获取倍速速度
float speed = mVideoPlayer.getSpeed();
//获取缓冲速度
long tcpSpeed = mVideoPlayer.getTcpSpeed();
//获取视频宽高
int[] videoSize = mVideoPlayer.getVideoSize();
//是否处于静音状态
boolean mute = mVideoPlayer.isMute();
复制代码
11.Controller相关Api
- Controller控制器相关的Api说明
//设置视频背景图
ImageView thumb = controller.getThumb();
Glide.with(this).load(R.drawable.image_default).into(controller.getThumb());
//设置视频标题
controller.setTitle("视频标题");
//添加自定义视图。每添加一个视图,都是方式层级树的最上层
CustomErrorView customErrorView = new CustomErrorView(this);
controller.addControlComponent(customErrorView);
//移除控制组件
controller.removeControlComponent(customErrorView);
//移除所有的组件
controller.removeAllControlComponent();
//隐藏播放视图
controller.hide();
//显示播放视图
controller.show();
//是否开启根据屏幕方向进入/退出全屏
controller.setEnableOrientation(true);
//显示移动网络播放提示
controller.showNetWarning();
//刘海的高度
int cutoutHeight = controller.getCutoutHeight();
//是否有刘海屏
boolean b = controller.hasCutout();
//设置是否适配刘海屏
controller.setAdaptCutout(true);
//停止刷新进度
controller.stopProgress();
//开始刷新进度,注意:需在STATE_PLAYING时调用才会开始刷新进度
controller.startProgress();
//判断是否锁屏
boolean locked = controller.isLocked();
//设置是否锁屏
controller.setLocked(true);
//取消计时
controller.stopFadeOut();
//开始计时
controller.startFadeOut();
//设置播放视图自动隐藏超时
controller.setDismissTimeout(8);
//销毁
controller.destroy();
复制代码
12.边播放边缓存api
- 如下所示
controller = new BasisVideoController(this);
//设置视频背景图
Glide.with(this).load(R.drawable.image_default).into(controller.getThumb());
//设置控制器
mVideoPlayer.setController(controller);
HttpProxyCacheServer server = new HttpProxyCacheServer(this);
String proxyVideoUrl = server.getProxyUrl(URL_AD);
mVideoPlayer.setUrl(proxyUrl);
mVideoPlayer.start();
复制代码
13.类似抖音视频预加载
- 如下所示,这个是针对ViewPager
//获取PreloadManager预加载管理者对象
mPreloadManager = PreloadManager.getInstance(this);
//在播放视频的时候
String playUrl = mPreloadManager.getPlayUrl(url);
VideoLogUtils.i("startPlay: " + "position: " + position + " url: " + playUrl);
mVideoPlayer.setUrl(playUrl);
//在页面滚动的时候
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int state) {
super.onPageScrollStateChanged(state);
if (state == VerticalViewPager.SCROLL_STATE_IDLE) {
mPreloadManager.resumePreload(mCurPos, mIsReverseScroll);
} else {
mPreloadManager.pausePreload(mCurPos, mIsReverseScroll);
}
}
});
复制代码 - 如下所示,这个是针对RecyclerView
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
/**
* 是否反向滑动
*/
private boolean mIsReverseScroll; @Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy>0){
//表示下滑
mIsReverseScroll = false;
} else {
//表示上滑
mIsReverseScroll = true;
}
} @Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == VerticalViewPager.SCROLL_STATE_IDLE) {
mPreloadManager.resumePreload(mCurPos, mIsReverseScroll);
} else {
mPreloadManager.pausePreload(mCurPos, mIsReverseScroll);
}
}
});
复制代码
14.视频播放器埋点
- 代码如下所示,写一个类,实现BuriedPointEvent即可。即可埋点视频的播放次数,播放进度,点击视频广告啥的,方便统一管理
public class BuriedPointEventImpl implements BuriedPointEvent {
/**
* 进入视频播放
* @param url 视频url
*/
@Override
public void playerIn(String url) {
}
/**
* 退出视频播放
* @param url 视频url
*/
@Override
public void playerDestroy(String url) {
}
/**
* 视频播放完成
* @param url 视频url
*/
@Override
public void playerCompletion(String url) {
}
/**
* 视频播放异常
* @param url 视频url
* @param isNetError 是否是网络异常
*/
@Override
public void onError(String url, boolean isNetError) {
}
/**
* 点击了视频广告
* @param url 视频url
*/
@Override
public void clickAd(String url) {
}
/**
* 退出视频播放时候的播放进度百度分
* @param url 视频url
* @param progress 视频进度,计算百分比【退出时候进度 / 总进度】
*/
@Override
public void playerOutProgress(String url, float progress) {
}
/**
* 视频切换音频
* @param url 视频url
*/
@Override
public void videoToMedia(String url) {
}
}
复制代码
15.播放器示例展示图
作者:杨充
链接:https://juejin.im/post/6884021420293259271
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
03.视频播放器Api说明的更多相关文章
- html5视频播放器 二 (功能实现及播放优化)
样式改写css,其中的一些按钮是在“阿里妈妈”上找的字体图标,就不向上传了. /* *CoolPlay视频播放器 * 2016年8月1日 * 627314658@qq.com * */ @font-f ...
- H5视频播放器属性与API控件,以及对程序的解释
一:理论 1.视频播放器的格式介绍 视频主要有三部分组成:视频.音频.编码格式 视频格式:avi.rmb.wmv.mpeg4.ogg.webm 2.H5的标签video的简单使用 <video ...
- Python应用03 使用PyQT制作视频播放器
作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁任何形式转载. 最近研究了Python的两个GUI包,Tkinter和PyQT.这两个GUI包的底层分别是Tcl/ ...
- 最简单的基于FFMPEG+SDL的视频播放器 ver2 (採用SDL2.0)
===================================================== 最简单的基于FFmpeg的视频播放器系列文章列表: 100行代码实现最简单的基于FFMPEG ...
- 最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0)
===================================================== 最简单的基于FFmpeg的视频播放器系列文章列表: 100行代码实现最简单的基于FFMPEG ...
- 打造自己的html5视频播放器
前段时间重新学习了一下html5的video部分,以前只是停留在标签的使用上,这一次决定深入了解相关的API,并运用这些API打造一个简单的视频播放器.所谓“打造自己的”,就是要自己重写video标签 ...
- 一款开源免费跨浏览器的视频播放器--videojs使用介绍
最近项目中的视频功能,需要做到浏览器全兼容,所以之前用html5实现的视频功能就需要进行改造了.在网上翻了个遍,试来试去,在所有的视频播放器中,就数它最实际了.首先我们来看看它的优点: 1.它是开源免 ...
- 分享一个基于HTML5实现的视频播放器
什么是hivideo? 最近一段时间在使用PhoneGap开发一个App应用,App需要播放视频,本想直接使用html5的video,但使用它在全屏播放时不支持横屏播放,只能放弃.最终决定还是自己封装 ...
- C语言基于GTK+Libvlc实现的简易视频播放器(二)
简易视频播放器-全屏播放 一.课程说明 上一次我们使用gtk+libvlc实现了一个最简单的视频播放器,可以实现点击按钮暂定和停止播放视频,以及同步显 示视频播放进度,但即使作为一个视频播放器,只有这 ...
- C语言基于GTK+Libvlc实现的简易视频播放器
小编心语:现下,各种视频播放软件层出不穷,竞争也越演越烈,不知道大家有木有这个想法,小编有时在想能不能做一款属于自己的视频播放器呢~小编特意去实验楼,整理出了这篇关于如何实现简易视频播放器的博文.简易 ...
随机推荐
- Kafka-启动时报错: ERROR Fatal error during KafkaServer startup. Prepare to shutdown
一.问题描述 在启动kafka时报错: ERROR Fatal error during KafkaServer startup. Prepare to shutdown (kafka.server. ...
- SpringCloud 注册中心Consul实战
介绍 Consul是HashiCorp公司推出的开源工具,Consul由Go语言开发,部署起来非常容易,只需要极少的可执行程序和配置文件,具有绿色.轻量级的特点.Consul是分布式的.高可用的. 可 ...
- spring boot+sqlite+mybatis实现增删改查例子
主要是更换了下sqlite的数据源而已,其他代码不变. 我都贴一下吧,这个算是比较通用的基础增删改查代码. 1.创建test.db 可以使用Idea自带的Database插件配置,也可以命令行创建,具 ...
- Java并发编程实例--19.在一个锁中使用多个条件
一个锁可能关联了一个或多个条件.这些条件可以在Condition接口中声名. 使用这些条件的目的是去控制一个锁并且可以检查一个条件是true或false,如果为false,则暂停直到 另一个线程来唤醒 ...
- Java常用编程类库
Java语言已经有许多非常成熟的开源基础类库,封装了日常开发中的各种常用操作,如:对象判空,字符串编码,本地缓存等等. 可以直接在项目中引入对应类库使用即可,或者参与完善相应类库的方法. 现将常用的基 ...
- 迭代器,map,filter,reduce,sorted函数---day12
1.迭代器 迭代器能被next调用,并不断返回下一个值的对象,叫作迭代器(迭代器是对象) 概念:迭代器指的是迭代取值的工具,迭代是一个重复的过程每次重复都是基于上一次的结果而继续单纯的重复不是迭代. ...
- java数组实现的超市管理系统(控制台)
说明:使用数组存储数据,针对用户功能1:增加用户2:删除用户3:修改用户:针对商品功能:1.显示所有商品2.修改商品信息3.添加商品信息4.删除商品信息5.查询商品信息 效果展示 ========== ...
- 【图论#02】岛屿系列题(数量、周长、最大面积),flood fill算法的代码实现与优化
岛屿数量 给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量. 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成. 此外,你可以假设该网 ...
- ASP.NET Core MVC应用模型的构建[3]: Controller的收集
从编程的角度来看,一个MVC应用是由一系列Controller类型构建而成的,所以对于一个代表应用模型的ApplicationModel对象来说,它的核心就是Controllers属性返回的一组Con ...
- SpringBoot面试题的零碎整理
面试题1:简述一下Springboot相对SSM做了哪些提升? 首先,SpringBoot是采用"约定大于配置"(Convention over Configuration)的理念 ...