MBProgressHUD源码(上)
本篇博文记录MBProgressHUD源码学习过程,从官方提供的Demo项目入手,一步步了解其代码结构,学习它使用的技术,体会作者的编程思想。
一、结构
我们先来看下MBProgressHUD的结构,查看其类的定义。
1.MBProgressHUD是UIView的子类。
2.属性:
1.
//代理,<MBProgressHUDDelegate>仅定义了一个方法:- (void)hudWasHidden:(MBProgressHUD *)hud;用于执行HUD隐藏之后的操作
@property (weak, nonatomic) id<MBProgressHUDDelegate> delegate;
//执行HUD隐藏之后的操作的Block,目的同上
@property (copy, nullable) MBProgressHUDCompletionBlock completionBlock;
2.
//延迟时间,若任务在graceTime到时之前就完成了,HUD不再展示,即防止为短时间任务显示HUD
@property (assign, nonatomic) NSTimeInterval graceTime;
//最短展示时间,防止HUD隐藏的过快
@property (assign, nonatomic) NSTimeInterval minShowTime;
//配置HUD是否隐藏之后就从其superview上移除。默认NO
@property (assign, nonatomic) BOOL removeFromSuperViewOnHide;
3.
//指定进度条的样式,包括菊花、圆饼、环形、水平进度条、自定义样式和纯文本等
@property (assign, nonatomic) MBProgressHUDMode mode;
//内容(label+indicator+customView)颜色
@property (strong, nonatomic, nullable) UIColor *contentColor;
//显示和隐藏时的动画类型:Fade(淡入淡出)、Zoom(放大显示缩小隐藏)、ZoomIn、ZoomOut
@property (assign, nonatomic) MBProgressHUDAnimation animationType;
//内容框(bezelView)距离中心位置的偏移,例如CGPointMake(0.f, MBProgressMaxOffset),内容框会在底部居中
@property (assign, nonatomic) CGPoint offset;
@property (assign, nonatomic) CGFloat margin;//各元素到HUD的边距
@property (assign, nonatomic) CGSize minSize;//内容框的最小尺寸
@property (assign, nonatomic, getter = isSquare) BOOL square;//强制HUD为方形
@property (assign, nonatomic, getter=areDefaultMotionEffectsEnabled) BOOL defaultMotionEffectsEnabled;//内容框(bezelView)是否受设备加速计的影响,默认YES
4.
@property (assign, nonatomic) float progress;//进度
@property (strong, nonatomic, nullable) NSProgress *progressObject;//进度对象,用于更新进度条
5.
//内容框,即展示实际内容(文本、indicator)的矩形框
@property (strong, nonatomic, readonly) MBBackgroundView *bezelView;
//背景试图,会覆盖整个屏幕
@property (strong, nonatomic, readonly) MBBackgroundView *backgroundView;
//自定义视图用于展示
@property (strong, nonatomic, nullable) UIView *customView;
@property (strong, nonatomic, readonly) UILabel *label;//文本
@property (strong, nonatomic, readonly) UILabel *detailsLabel;//文本下面的详细文本
@property (strong, nonatomic, readonly) UIButton *button;//文本下面的action button
3.其他相关类
(1) MBBackgroundView
- UIView的子类,在MBPRogressHUD中充当内容框(bezelView)和背景视图(backgroundView)两种角色。
- 提供两种样式:清晰样式(MBProgressHUDBackgroundStyleSolidColor)和模糊样式(MBProgressHUDBackgroundStyleBlur)
- 模糊样式是通过
UIVisualEffectView
和UIBlurEffect
实现的。
(2) MBRoundProgressView
- UIView的子类,展示为饼状/环形的进度条。
(3) MBBarProgressView
- UIView的子类,展示为条状的进度条。
(4) MBProgressHUDRoundedButton
- UIButton的子类,展示位圆角button,作为HUD上的功能按钮。
知识点:HUD中有个button属性如下:
/**
* A button that is placed below the labels. Visible only if a target / action is added.
*/
@property (strong, nonatomic, readonly) UIButton *button;
注意它的注释Visible only if a target / action is added
。也就是说,只有给button添加事件之后,该按钮才会展示出来。这是如何做到的呢?那就是重写UIView的函数- (CGSize)intrinsicContentSize
:
- (CGSize)intrinsicContentSize {
// Only show if we have associated control events
if (self.allControlEvents == 0) return CGSizeZero;
CGSize size = [super intrinsicContentSize];
// Add some side padding
size.width += 20.f;
return size;
}
这个函数用来设置控件的内置尺寸。可以看到,通过判断allControlEvents
的个数来判断button上是否有事件,如果有事件,就在原来内置的尺寸上加20。
二、代码追踪
了解了MBProgressHUD的基本结构之后,接下来我们就看看具体的功能是如何实现的。HUDDemo提供了15个样例,我们选取纯文本、加载(菊花)、条状进度条和自定义视图进行分析,其他的样例与它们类似。
1.纯文本(Text)
我们先从最简单的纯文本开始。启动HUDDemo项目,点开MBHudDemoViewController.m
文件,找到函数- (void)textExample{…}
,这个函数就是显示纯文本的处理函数:
- (void)textExample {
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
// Set the text mode to show only text.
hud.mode = MBProgressHUDModeText;
hud.label.text = NSLocalizedString(@"Message here!", @"HUD message title");
// Move to bottm center.
hud.offset = CGPointMake(0.f, MBProgressMaxOffset);
[hud hideAnimated:YES afterDelay:3.f];
}
① 进入到函数showHUDAddedTo:animated:
中查看MBProgressHUD实例的创建过程:
initWithView:
->initWithFrame:
->commonInit
使用
self.navigationController.view
的bounds初始化HUD,然后在commonInit
里指定动画类型(Fade)、HUD模式(菊花)、间距(20)、内容颜色(黑色半透明)。除此之外,还设置HUD为完全透明,背景色为clear,配置HUD的尺寸自动调整://保证上下间距比例不变、左右间距比例不变,即防止横竖屏切换时HUD位置错误
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
//让HUD的各个子视图自己控制自己的透明度,使其不受HUD透明度的影响
self.layer.allowsGroupOpacity = NO;
[self setupViews]
在这个函数中真正执行子视图的创建工作。
背景视图(backgroundView)
为类
MBBackgroundView
的实例。MBBackgroundView
实例默认会创建成白色半透明模糊效果,并覆盖全屏,但在本例中,创建完成之后会更改其style
为MBProgressHUDBackgroundStyleSolidColor
,并将背景色设置为透明(clear)。内容框(bezelView)
同为类
MBBackgroundView
实例,是实际展示内容的View(即中间的黑框),包含文本、indicator、进度条等。bezelView
会默认创建成白色半透明模糊效果,但frame为0。创建后会设置其边角半径为5。知识点:作者为bezelView添加了MotionEffect,也就是说在bezelView显示的时候,它会根据手机的倾斜方向调整自己的位置!
- (void)updateBezelMotionEffects {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 || TARGET_OS_TV
MBBackgroundView *bezelView = self.bezelView;
if (![bezelView respondsToSelector:@selector(addMotionEffect:)]) return; if (self.defaultMotionEffectsEnabled) {
CGFloat effectOffset = 10.f;
UIInterpolatingMotionEffect *effectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
effectX.maximumRelativeValue = @(effectOffset);
effectX.minimumRelativeValue = @(-effectOffset); UIInterpolatingMotionEffect *effectY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
effectY.maximumRelativeValue = @(effectOffset);
effectY.minimumRelativeValue = @(-effectOffset); UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc] init];
group.motionEffects = @[effectX, effectY]; [bezelView addMotionEffect:group];
} else {
NSArray *effects = [bezelView motionEffects];
for (UIMotionEffect *effect in effects) {
[bezelView removeMotionEffect:effect];
}
}
#endif
}
label和detailsLabel
设置显示文字的label,其中detailsLabel允许多行。
button
为
MBProgressHUDRoundedButton
的实例,作为HUD上的功能按钮,比如进度条下方可以显示一个"取消"按钮。topSpacer和bottomSpacer
均为
UIView
的实例,用于调节上下间距的辅助View。设置label、detailsLabel及button的抗压系数,并添加到父视图上。
for (UIView *view in @[label, detailsLabel, button]) {
view.translatesAutoresizingMaskIntoConstraints = NO;//自己手动管理约束
[view setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisHorizontal];//设置水平抗压缩系数,值越大,越不容易被压缩
[view setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisVertical];//设置垂直抗压缩系数,值越大,越不容易被压缩
[bezelView addSubview:view];
}
[self updateIndicators]
HUD的
indicator
是UIView
的实例,用来记录HUD上显示的视图,进度条、加载图标(菊花)、自定义视图等都是用HUD的indicator
属性记录的。在函数- (void)updaetIndicators
中,根据HUD的mode值配置不同的indicator。最后会调用[self setNeedsUpdateConstraints]
触发约束更新函数-(void)updateConstraints
来更新UI。[self registerForNotifications]
注册通知,处理屏幕旋转的问题。
② 在创建完HUD之后,会调用[hud showAnimated:animated];
将HUD展示到屏幕上。事实上,虽然当前HUD已经在屏幕上了,但由于初始化HUD的时候bezelView的frame为0,用户看不到。
③ 配置HUD实例的属性
hud.mode = MBProgressHUDModeText;//设置hud只显示纯文本
hud.label.text = NSLocalizedString(@"Message here!", @"HUD message title");//设置文本内容
hud.offset = CGPointMake(0.f, MBProgressMaxOffset);//设置hud相对于中心位置的偏移
在mode的setter函数中会调用- (void)updateIndicators
,根据mode的新值重新配置indicator,然后调用- (void)setNeedsUpdateConstraints
触发-(void)updateConstraints
来更新UI。而在offset的setter函数中会直接调用- (void)setNeedsUpdateConstraints
触发-(void)updateConstraints
来更新UI。
④ 在函数- (void)updateConstraints
中更新布局:
- 删除所有控件的constraints
- 通过
NSLayoutConstraint
重新设置constraints
//1.以屏幕中心为基准,应用offset。priority = 998
CGPoint offset = self.offset;
NSMutableArray *centeringConstraints = [NSMutableArray array];
//x
[centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.f constant:offset.x]];
//y
[centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.f constant:offset.y]];
//为每个constraints设置priority
[self applyPriority:998.f toConstraints:centeringConstraints];
[self addConstraints:centeringConstraints];
//2.设置最小间距约束,priority = 999
NSMutableArray *sideConstraints = [NSMutableArray array];
[sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[bezel]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bezel)]];
[sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=margin)-[bezel]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bezel)]];
[self applyPriority:999.f toConstraints:sideConstraints];
[self addConstraints:sideConstraints];
//3.bezel的最小尺寸约束 priority = 997
CGSize minimumSize = self.minSize;
if (!CGSizeEqualToSize(minimumSize, CGSizeZero)) {
NSMutableArray *minSizeConstraints = [NSMutableArray array];
[minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.width]];
[minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.height]];
[self applyPriority:997.f toConstraints:minSizeConstraints];
[bezelConstraints addObjectsFromArray:minSizeConstraints];
}
//4.方形约束 priority=997
if (self.square) {
NSLayoutConstraint *square = [NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeWidth multiplier:1.f constant:0];
square.priority = 997.f;
[bezelConstraints addObject:square];
}
//5.根据margin和设置上下spacer的间距约束
[topSpacer addConstraint:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]];
[bottomSpacer addConstraint:[NSLayoutConstraint constraintWithItem:bottomSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]];
[bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bottomSpacer attribute:NSLayoutAttributeHeight multiplier:1.f constant:0.f]];
//6.设置bezel子视图(topSpacer、label、detailLabel、button、bottomSpacer)的约束
[subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
// Center in bezel
[bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeCenterX multiplier:1.f constant:0.f]];
// Ensure the minimum edge margin is kept
[bezelConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[view]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(view)]];
// Element spacing
if (idx == 0) {
// First, ensure spacing to bezel edge
[bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeTop multiplier:1.f constant:0.f]];
} else if (idx == subviews.count - 1) {
// Last, ensure spacing to bezel edge
[bezelConstraints addObject:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]];
}
if (idx > 0) {
// Has previous
NSLayoutConstraint *padding = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:subviews[idx - 1] attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f];
[bezelConstraints addObject:padding];
[paddingConstraints addObject:padding];
}
}];
[bezel addConstraints:bezelConstraints];
self.bezelConstraints = bezelConstraints;
self.paddingConstraints = [paddingConstraints copy];
[self updatePaddingConstraints];//在该函数里,根据子视图的可视性(hidden),设置子视图的上下间距(为4)
通过上面的priority可以知道优先级:最小间距约束>bezel的偏移约束>bezel最小尺寸约束=方形约束。因此,如果你设置了hud.square = YES
,但是实际bezel并没有变为方形,则很可能是因为上面的这几个约束之间存在冲突,系统采用了高优先级的约束而忽略了square约束。不信你可以把square优先级改为1000试试看:)
知识点:这里出现了一个宏NSDictionaryOfVariableBindings
,它可以用来方便的创建NSDictionary:
UIView *view1 = [UIView new];
UIView *view2 = [UIView new];
NSDictionary *dict = NSDictionaryOfVariableBindings(view1,view2);//{@"view1":view1,@"view2":view2}
总结:
至此,我们来总结下纯文本HUD的整个创建及显示流程:
- 调用
[MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]
创建HUD实例:包括配置属性默认值(动画类型、HUD样式、间距、内容颜色等),初始化view(backgroundView、bezelView、label、detailLabel、button、topSpacer、bottomSpacer),且会默认创建一个indicator。之后hud会显示在屏幕上,但由于约束未触发,因此用户看不到。hud.mode = MBProgressHUDModeText
。HUD会根据mode的值去隐藏indicator,并更新约束。hud.label.text = NSLocalizedString(@"Message here!", @"HUD message title")
设置要显示的文字。hud.offset = CGPointMake(0.f, MBProgressMaxOffset)
设置bezelView的偏移属性:让其显示在最底部。并更新约束。[hud hideAnimated:YES afterDelay:3.f]
设置一个延迟timer,在3s之后隐藏hud。隐藏之后调用completionBlock
和代理方法- (void)hudWasHidden:(MBProgressHUD *)hud;
。
2.加载(菊花)
加载样式表现为一个旋转的菊花,底部也可包含"Loading…"等字样提示。我们以包含"Loading…"字样的HUD为例剖析其内部原理。代码如下:
- (void)labelExample {
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
// Set the label text.
hud.label.text = NSLocalizedString(@"Loading...", @"HUD loading title");
// You can also adjust other label properties if needed.
// hud.label.font = [UIFont italicSystemFontOfSize:16.f];
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
[self doSomeWork];
dispatch_async(dispatch_get_main_queue(), ^{
[hud hideAnimated:YES];
});
});
}
- 调用
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
创建HUD实例,过程跟纯文本是一样的。 hud.label.text = NSLocalizedString(@"Loading...", @"HUD loading title");
配置提示文案为"Loading"。- 之后在
global_queue
里面执行任务,完成任务之后回到主线程隐藏HUD。
通过分析纯文本HUD的创建过程我们知道,hud在初始化的时候,它的mode默认为MBProgressHUDModeIndeterminate
,也就是说单纯的调用MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
创建出来的HUD就是带有菊花加载控件的HUD,我们接下来做的就是给它的label赋上文案即可。
3.条状进度条
MBProgressHUD提供了三种样式的进度条:条状、饼状、环状。其中饼状和环状差不多,接下来我们分析下条状进度条的实现原理:
- (void)barDeterminateExample {
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
// Set the bar determinate mode to show task progress.
hud.mode = MBProgressHUDModeDeterminateHorizontalBar;
hud.label.text = NSLocalizedString(@"Loading...", @"HUD loading title");
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
// Do something useful in the background and update the HUD periodically.
[self doSomeWorkWithProgress];
dispatch_async(dispatch_get_main_queue(), ^{
[hud hideAnimated:YES];
});
});
}
- 调用
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
创建HUD实例,过程跟纯文本是一样的。 hud.mode = MBProgressHUDModeDeterminateHorizontalBar;
设置mode为条状进度条。在mode的setter方法中会调用- (void)updateIndicator
创建进度条indicator。- 进度条indicator是类
MBBarProgressView
的实例。创建时默认宽为120,高为20,内容高度(intrinsicContentSize
)为10。它的样式是在- (void)drawRect
中绘制的。在其progress
属性的setter方法中调用了-(void)setNeedsDisplay
从而触发- (void)drawRect
来更新进度。 hud.label.text = NSLocalizedString(@"Loading...", @"HUD loading title");
配置HUD提示文案为"Loading"。
4.自定义视图
MBProgressHUD提供了显示自定义视图的功能。在Demo中是展示一个对勾。
- (void)customViewExample {
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
// Set the custom view mode to show any view.
hud.mode = MBProgressHUDModeCustomView;
// Set an image view with a checkmark.
UIImage *image = [[UIImage imageNamed:@"Checkmark"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
hud.customView = [[UIImageView alloc] initWithImage:image];
// Looks a bit nicer if we make it square.
hud.square = YES;
// Optional label text.
hud.label.text = NSLocalizedString(@"Done", @"HUD done title");
[hud hideAnimated:YES afterDelay:3.f];
}
- 调用
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
创建HUD实例,过程跟纯文本是一样的。 hud.mode = MBProgressHUDModeCustomView;
设置mode为自定义视图。接下来将需要展示的自定义视图赋值给hud的customView
属性。在customView
属性的setter方法中会调用- (void)updateIndicators
将customView
添加到HUD上。- 为了让界面美观,规定hud显示为方形:
hud.square = YES;
。 hud.label.text = NSLocalizedString(@"Loading...", @"HUD loading title");
配置HUD提示文案为"Loading"。
至此,我们已经简单了解了MBProgressHUD的整个代码结构及使用流程,这已经足够我们去创建和使用符合我们需求的HUD了。但其实MBProgressHUD的源码中还包含不少高级的技术细节,我们将在下篇文章中一个个分析学习。
MBProgressHUD源码(上)的更多相关文章
- 在Activiti官方源码上提交的两个bugfix
前段时间在Activiti官方源码上提交了两个bugfix,截图为证. 第1个是BPMN model输出的bug:
- [转]MBProgressHUD 源码分析
源码来源: https://github.com/jdg/MBProgressHUD 版本:0.9.1 MBProgressHUD是一个显示HUD窗口的第三方类库,用于在执行一些后台任务时,在程序中显 ...
- 使用git将Android源码上传到github
下面举Android的Browser源码通过git保存到github上 首先在github.com官网new repository一个仓库 在Repository name哪里填入Browser然后创 ...
- 从源码上分析ListView的addHeaderView和setAdapter的调用顺序
ListView想要添加headerview的话,就要通过addHeaderView这个方法,然后想要为ListView设置数据的话,就要调用setAdapter方法了.但是,在调用addHeader ...
- 从源码上理解Netty并发工具-Promise
前提 最近一直在看Netty相关的内容,也在编写一个轻量级的RPC框架来练手,途中发现了Netty的源码有很多亮点,某些实现甚至可以用苛刻来形容.另外,Netty提供的工具类也是相当优秀,可以开箱即用 ...
- 硬核干货:4W字从源码上分析JUC线程池ThreadPoolExecutor的实现原理
前提 很早之前就打算看一次JUC线程池ThreadPoolExecutor的源码实现,由于近段时间比较忙,一直没有时间整理出源码分析的文章.之前在分析扩展线程池实现可回调的Future时候曾经提到并发 ...
- 源码上看 .NET 中 StringBuilder 拼接字符串的实现
前几天写了一篇StringBuilder与TextWriter二者之间区别的文章(链接).当时提了一句没有找到相关源码,于是随后有很多热心人士给出了相关的源码链接(链接),感谢大家.这几天抽了点时间查 ...
- 带着萌新看springboot源码11(springboot启动原理 源码上)
通过前面这么多讲解,springboot原理应该也大概有个轮廓了,一些基本的配置,从客户端url到controller(配置一些要用的组件,servlet三大组件,处理器映射器,拦截器,视图解析器这些 ...
- 带着萌新看springboot源码8(spring ioc源码上)
emmm.....这次先不说springboot原理,先好好回顾一下以前的注解版spring原理,先把spring原理了解清晰了,再看springboot原理更容易. 要说起spring,最重要的就是 ...
随机推荐
- 常用类-excel转csv
public class ExcelFileHelper { public static bool SaveAsCsv(string excelFilePath, string destination ...
- Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之二 || 后端项目搭建
本文梯子 前言 1..net core 框架性能测试 2..net core 执行过程 3.中间件执行过程 4.AOP切面 5.整体框架结构与数据库表UML 一.创建第一个Core 1.SDK 安装 ...
- 用Python制作的一本道生成器,最后笑喷了!
今天皮一下,众所周知,一本道是一本正经的胡说八道的简称,想必写过议论文的小伙伴,都知道引经据典是议论文高分必备,套上名人的话更加具有说服力是语文老师必教的知识点. 所以呢,今天介绍的这个生成器就走的是 ...
- python-pyppeteer模块使用汇总
一.简单代码示例 import asyncio from pyppeteer import launch async def main(): browser = await launch() page ...
- bayaim_mysql5.6下table_open_cache参数
bayaim_mysql5.6下table_open_cache参数_2017年12月26日10:51:58 原创 作者:bayaim 时间:2017-12-26 10:57:17 1 0删除编辑 ( ...
- 解决Python3.6.5+Django2.0集成xadmin后台点击添加或者内容详情报 list index out of range 的错误
一 问题说明在创建Model的时候,如果存在类型是DateTimeField的字段,则在xadmin后端管理界面里,对该Model进行添加操作的时候,会报list index out of range ...
- Ubuntu笔记本安装高级电源管理工具TLP
Ubuntu系统下的笔记本电脑电量总是下降的很快,尽管目前系统对电源管理的优化已经进步了不少,但还是需要一些工具来辅助. TLP是一款Linux下的高级电源管理工具,相信很多Linux用户会用到它. ...
- Codeforces Round #600 (Div. 2)
传送门 A. Single Push 直接乱搞即可. Code /* * Author: heyuhhh * Created Time: 2019/11/16 22:36:20 */ #include ...
- 如何解决android 通知栏不显示的问题
android 8.0 以后的版本,在创建通知栏的时候,加了一个channelId的东西.要想在上述版本中显示通知,总共分两步 1.创建Channel if (Build.VERSION.SDK_IN ...
- luoguP4022 [CTSC2012]熟悉的文章
题意 显然这个\(L\)是可以二分的,我们只需要判断\(L\)是否合法即可. 显然有一个\(O(n^2)\)的DP: 设\(f_i\)表示当前匹配到\(i\)的最大匹配长度. \(f_i=max(f_ ...