当前位置: 首页 > news >正文

android 动画懒加载,Android - 懒加载

1.什么是懒加载,为什么要用懒加载?

如果我们的项目中使用了ViewPager+Framgment实现底部Tab可点可滑,那么我们都知道ViewPager有预加载功能,通过viewpager.setOffscreenPageLimit();来设置,不设置默认加载上一个和下一个Fragment页面,带上本身也就是三个页面(当然如果你刚进入就是首页,那么它会加载首页和下一个页面,因为首页上面没有页面呀)。预加载功能会暴露一个问题,比如我刚进入加载首页的数据,但是因为有预加载功能,那么就会执行下一个Tab对应的Fragmeng的生命周期,如果我下一个Tab页数据量小还好,如果我有比较耗时的操作或者网络请求,势必会影响程序的性能,影响用户的体验。那么我们要做的就是禁止ViewPager预加载或者提供一个只在Fragemnt可见的情况下,才去进行耗时操作的方法,只要Fragmeng可见我们就执行该方法。

2.懒加载解决方式

2.1 尝试设置setOffscreenPageLimit(失败)

之前想既然setOffscreenPageLimit可以设置,那我就将其设置为0,结果“然并卵”,查看源码如下:

8d1fe9ecb445

image.png

可以看到如果我们设置的值,小于DEFAULT_OFFSCREEN_PAGES这个常量值,那么就会被赋值为DEFAULT_OFFSCREEN_PAGES,那么我们看看DEFAULT_OFFSCREEN_PAGES值是多少:

8d1fe9ecb445

image.png

也就是你设置的setOffscreenPageLimit要大于1才可以生效

2.2 试试懒加载

我们先来看看我们的页面:

8d1fe9ecb445

image.png

就是正常的viewpager+fragment,每个页面有一个TextView,可点可划。三个Fragment依次是:HomeFragment,InvestFragment,UserFragment,

本次要用到的生命周期的方法是:

onCreatedView + onResume + onPause + onDestroyView

本次要用到的非生命周期的方法是:setUserVisibleHint

简单介绍一下此方法:当fragment被用户可见时,setUserVisibleHint()会调用且传入true值,当fragment不被用户可见时,setUserVisibleHint()则得到false值,此方法先于生命周期方法执行

Fragment 主要的三个状态:第一次可见,每次可见,每次不可见

对于ViewPager+Fragment使用过程中的三种情况

(1) 使用 FragmentPagerAdapter ,FragmentPagerStateAdapter不设置 setOffscreenPageLimit数,采用默认方式

(2)使用 FragmentPagerAdapter ,FragmentPagerStateAdapter设置 setOffscreenPageLimit数,设置为底部Tab总数

(3)使用 FragmentPagerAdapter ,FragmentPagerStateAdapter进入到其他页面或者点击Home键,返回到桌面。

其他注意的是:使用FragmentPagerAdapter 和FragmentPagerStateAdapter的区别在于FragmentPagerStateAdapter会在Fragment不可见的时候走 detach,而FragmentPagerAdapter不会。

当然我测试用的是FragmentPagerAdapter,我们先看一看正常滑动,不设置setOffscreenPageLimit(),Fragment生命周期是怎么走的,先写一个BaseLazyLoadFragment类继承自Fragment.重写我们刚才说的生命周期的方法,首页等Fragment继承BaseLazyLoadFragment打印生命周期(默认进来先加载首页):

BaseLazyLoadFragment部分代码如下

8d1fe9ecb445

image.png

Fragment代码如下

8d1fe9ecb445

image.png

不设置setOffscreenPageLimit(),FragmentPagerAdapter 结果如下

8d1fe9ecb445

8d1fe9ecb445

image.png

不设置setOffscreenPageLimit(),FragmentPagerStateAdapter 结果如下:

这个结果我之前有过测试,直接告诉你们把区别是:FragmentPagerStateAdapter 会走一下两个生命周期方法,包括从切到Home页面在返回这是一下走两个生命周期方法。

设置setOffscreenPageLimit()个数为总Tab数,FragmentPagerAdapter 和FragmentPagerStateAdapter结果一致,如下:

设置setOffscreenPageLimit为总数之后,一开始就加载了所有的Fragment

com.hxzk_bj_demo E/HomeFragment: isVisibleToUser------>false

com.hxzk_bj_demo E/InvestFragment:isVisibleToUser------>false

com.hxzk_bj_demo E/UserFragment: isVisibleToUser------>false

com.hxzk_bj_demo E/HomeFragment: isVisibleToUser------>true

com.hxzk_bj_demo E/HomeFragment: ------>onCreateView

com.hxzk_bj_demo E/HomeFragment: ------>onStart

com.hxzk_bj_demo E/HomeFragment: ------>onResume

com.hxzk_bj_demo E/InvestFragment: ------>onCreateView

com.hxzk_bj_demo E/UserFragment: ------>onCreateView

com.hxzk_bj_demo E/InvestFragment: ------>onStart

com.hxzk_bj_demo E/InvestFragment: ------>onResume

com.hxzk_bj_demo E/UserFragment: ------>onStart

com.hxzk_bj_demo E/UserFragment: ------>onResume

//第一个Fragment切换到第二个Fragment

com.hxzk_bj_demo E/HomeFragment: isVisibleToUser------>false

com.hxzk_bj_demo E/InvestFragment: isVisibleToUser------>true

//第二个Fragment切换到第三个Fragment

com.hxzk_bj_demo E/InvestFragment:isVisibleToUser------>false

com.hxzk_bj_demo E/UserFragment: isVisibleToUser------>true

//点击Home

com.hxzk_bj_demo E/HomeFragment: ------>onPause

com.hxzk_bj_demo E/InvestFragment: ------>onPause

com.hxzk_bj_demo E/UserFragment: ------>onPause

//点击Home后返回

com.hxzk_bj_demo E/HomeFragment: ------>onStart

com.hxzk_bj_demo E/InvestFragment: ------>onStart

com.hxzk_bj_demo E/UserFragment: ------>onStart

com.hxzk_bj_demo E/HomeFragment: ------>onResume

com.hxzk_bj_demo E/InvestFragment: ------>onResume

com.hxzk_bj_demo E/UserFragment: ------>onResume

没啥的。

针对不设置setOffscreenPageLimit(),FragmentPagerAdapter 结果我们分析一下:可以看到进入到第一个Fragment的时候,也执行了下一个Fragment的生命周期,执行了不必要的操作。那大家有没有发现,如果那个Fragment的状态为可见其setUserVisibleHint的值就为true,其余Fragment的值为false,那我们只需要判断,如果setUserVisibleHint的值就为true即改Fragment为可见状态,我们就执行耗时操作,其他Fragment为false,就不执行网络请求的操作呗。那我们写一个公共的方法,注意此方法执行,要放到onActivityCreate()之后,否则我请求回来的数据载体控件的Activity都没有创建,所以我要定义几个变量来查看Fragment的状态,我们之前也说了Fragement有首次可见,可见和不可见三种状态,代码如下:

View rootView;

/**当前Fragment是否首次可见,默认是首次可见**/

private boolean mIsFirstVisible = true;

/**当前Fragment的View是否已经创建**/

private boolean isViewCreated = false;

/**当前Fragment的可见状态,一种当前可见,一种当前不可见**/

private boolean currentVisibleState = false;

@Nullable

@Override

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

LogUtil.e(getClass().getSimpleName(),"-----> onCreateView");

if(rootView == null){

rootView = inflater.inflate(getLayoutId(), container, false);

initView(rootView);

}

isViewCreated=true;//在onCreateView执行完毕,将isViewCreated改为true;

return rootView;

}

不同生命周期变量值的变更及涉及的相关代码:

onStart

@Override

public void onStart() {

super.onStart();

LogUtil.e(getClass().getSimpleName(),"-----> onStart");

//isHidden()是Fragment是否处于隐藏状态和isVisible()有区别

//getUserVisibleHint(),Fragement是否可见

if(!isHidden()&& getUserVisibleHint()){//如果Fragment没有隐藏且可见

//执行分发的方法,三种结果对应自Fragment的三个回调,对应的操作,Fragment首次加载,可见,不可见

disPatchFragment(true);

}

}

onResume

@Override

public void onResume() {

super.onResume();

LogUtil.e(getClass().getSimpleName(),"-----> onResume");

if(!mIsFirstVisible){

//表示点击home键又返回操作,设置可见状态为ture

if(!isHidden()&& !getUserVisibleHint() && currentVisibleState){

disPatchFragment(true);

}

}

}

onPause

@Override

public void onPause() {

super.onPause();

//表示点击home键,原来可见的Fragment要走该方法,更改Fragment的状态为不可见

if(!isHidden()&& getUserVisibleHint()){

disPatchFragment(false);

}

}

onDestroyView

@Override

public void onDestroyView() {

super.onDestroyView();

LogUtil.e(getClass().getSimpleName(),"-----> onStart");

//当 View 被销毁的时候我们需要重新设置 isViewCreated mIsFirstVisible 的状态

isViewCreated = false;

mIsFirstVisible = true;

}

Fragment不同状态对应的回调方法

/**

*

* @param visible Fragment当前是否可见,然后调用相关方法

*/

public void disPatchFragment(boolean visible){

currentVisibleState=visible;

if(visible){//Fragment可见

if(mIsFirstVisible){//可见又是第一次

mIsFirstVisible=false;//改变首次可见的状态

onFragmentFirst();

}else{//可见但不是第一次

LogUtil.e(getClass().getSimpleName(),"可见");

}

}else {//不可见

LogUtil.e(getClass().getSimpleName(),"不可见");

}

};

//Fragemnet首次可见的方法

public void onFragmentFirst(){

LogUtil.e(getClass().getSimpleName(),"首次可见");

};

//Fragemnet可见的方法

public void onFragmentVisble(){//子Fragment调用次方法,执行可见操作

LogUtil.e(getClass().getSimpleName(),"可见");

};

//Fragemnet不可见的方法

public void onFragmentInVisible(){

LogUtil.e(getClass().getSimpleName(),"不可见");

};

最后来一个总的代码:

public abstract class BaseLazyLoadFragment extends android.support.v4.app.Fragment {

View rootView;

/**当前Fragment是否首次可见,默认是首次可见**/

private boolean mIsFirstVisible = true;

/**当前Fragment的View是否已经创建**/

private boolean isViewCreated = false;

/**当前Fragment的可见状态,一种当前可见,一种当前不可见**/

private boolean currentVisibleState = false;

@Nullable

@Override

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

LogUtil.e(getClass().getSimpleName(),"-----> onCreateView");

if(rootView == null){

rootView = inflater.inflate(getLayoutId(), container, false);

initView(rootView);

}

isViewCreated=true;//在onCreateView执行完毕,将isViewCreated改为true;

return rootView;

}

@Override

public void setUserVisibleHint(boolean isVisibleToUser) {

super.setUserVisibleHint(isVisibleToUser);

LogUtil.e(getClass().getSimpleName(),"----->"+isVisibleToUser);

if (isViewCreated) {

if (isVisibleToUser && !currentVisibleState) {//Fragment可见且状态不是可见(从一个Fragment切换到另外一个Fragment,后一个设置状态为可见)

disPatchFragment(true);

} else if (!isVisibleToUser && currentVisibleState) {//Fragment不可见且状态是可见(从一个Fragment切换到另外一个Fragment,前一个更改状态为不可见)

disPatchFragment(false);

}

}

}

/**返回子Fragment的布局id**/

public abstract int getLayoutId();

/**初始化View的方法**/

public abstract void initView(View rootView);

@Override

public void onStart() {

super.onStart();

LogUtil.e(getClass().getSimpleName(),"-----> onStart");

//isHidden()是Fragment是否处于隐藏状态和isVisible()有区别

//getUserVisibleHint(),Fragement是否可见

if(!isHidden()&& getUserVisibleHint()){//如果Fragment没有隐藏且可见

//执行分发的方法,三种结果对应自Fragment的三个回调,对应的操作,Fragment首次加载,可见,不可见

disPatchFragment(true);

}

}

@Override

public void onResume() {

super.onResume();

LogUtil.e(getClass().getSimpleName(),"-----> onResume");

if(!mIsFirstVisible){

//表示点击home键又返回操作,设置可见状态为ture

if(!isHidden()&& !getUserVisibleHint() && currentVisibleState){

disPatchFragment(true);

}

}

}

@Override

public void onPause() {

super.onPause();

//表示点击home键,原来可见的Fragment要走该方法,更改Fragment的状态为不可见

if(!isHidden()&& getUserVisibleHint()){

disPatchFragment(false);

}

}

@Override

public void onDestroyView() {

super.onDestroyView();

LogUtil.e(getClass().getSimpleName(),"-----> onStart");

//当 View 被销毁的时候我们需要重新设置 isViewCreated mIsFirstVisible 的状态

isViewCreated = false;

mIsFirstVisible = true;

}

/**

*

* @param visible Fragment当前是否可见,然后调用相关方法

*/

public void disPatchFragment(boolean visible){

currentVisibleState=visible;

if(visible){//Fragment可见

if(mIsFirstVisible){//可见又是第一次

mIsFirstVisible=false;//改变首次可见的状态

onFragmentFirst();

}else{//可见但不是第一次

LogUtil.e(getClass().getSimpleName(),"可见");

}

}else {//不可见

LogUtil.e(getClass().getSimpleName(),"不可见");

}

};

//Fragemnet首次可见的方法

public void onFragmentFirst(){

LogUtil.e(getClass().getSimpleName(),"首次可见");

};

//Fragemnet可见的方法

public void onFragmentVisble(){//子Fragment调用次方法,执行可见操作

LogUtil.e(getClass().getSimpleName(),"可见");

};

//Fragemnet不可见的方法

public void onFragmentInVisible(){

LogUtil.e(getClass().getSimpleName(),"不可见");

};

}

我们的Fragment只需要继承BaseLazyLoadFragment,然后对应调用首次可见方法,再次可见方法,不可见方法做相应的操作就可以了。

懒加载进阶

我们上面说的是一层的ViewPager加Fragment,但大家也一定遇到过Fragemgt中又来了一层ViewPager+Fragment,如图:

8d1fe9ecb445

那这种的怎么办呢?之前的方法还管用不,别急,我们先看看其生命周期打印:

纳尼,InvestFragment(投资)内部第一个Tab,Invest_MineFragment竟然执行了首次可见的方法,要知道此时的InvestFragmetn都没有显示。

针对此问题,我的解决方法是,先判断父Fragment如果没有显示,那么不触发我们定义的方法,代码如下:

/**

*判断多层嵌套的父Fragment是否显示

*/

private boolean isParentFragmentInvisible() {

//获取父Fragment的可见状态

BaseLazyLoadFragment fragment = (BaseLazyLoadFragment) getParentFragment();

//如果两个都满足即父Fragment不为空且父Fragment不可见,返回true

return fragment != null && !fragment.getCurrentVisibleState();

}

private boolean getCurrentVisibleState() {

return currentVisibleState;

}

ok,我们在运行一下,打印如下:

8d1fe9ecb445

image.png

感觉没啥问题?

别急,还有剩余部分打印信息:

8d1fe9ecb445

image.png

也就是我们还需要一个第一个子Fragment的状态信息:解决思路如下:

由于父Fragment的执行在子Fragment之前,所以,当我们在父 Fragment 分发完成自己的可见事件后,让子 Fragment 再次调用自己的可见事件分发方法,这次我们让 isParentFragmentVsible() 返回 false ,可见状态将会正确分发了,有点类似于父类完成后,又调用方法刷新子类

/**

*

* @param visible Fragment当前是否可见,然后调用相关方法

*/

public void disPatchFragment(boolean visible){

String aa =getClass().getSimpleName();

//如果父Fragment不可见,则不向下分发给子Fragment

if(visible && isParentFragmentVsible())return;

currentVisibleState=visible;

if(visible){//Fragment可见

if(mIsFirstVisible){//可见又是第一次

mIsFirstVisible=false;//改变首次可见的状态

onFragmentFirst();

}//可见但不是第一次

onFragmentVisble();

//可见状态的时候内层 fragment 生命周期晚于外层 所以在 onFragmentResume 后分发

dispatchChildFragmentVisibleState(true);

}else {//不可见

onFragmentInVisible();

dispatchChildFragmentVisibleState(false);

}

};

/**

* 父Fragment分发完成之后再次调用,重新分发给子Fragment

* @param visible

*/

private void dispatchChildFragmentVisibleState(boolean visible) {

FragmentManager childFragmentManager = getChildFragmentManager();

@SuppressLint("RestrictedApi") List fragments = childFragmentManager.getFragments();

if(fragments != null){

if (!fragments.isEmpty()) {

for (Fragment child : fragments) {

if (child instanceof BaseLazyLoadFragment && !child.isHidden() && child.getUserVisibleHint()) {

((BaseLazyLoadFragment) child).disPatchFragment(visible);

}

}

}

}

}

这样就ok了,然后我们点击home键:

8d1fe9ecb445

这又是什么问题,Invest_YourFragment为什么走了两边?

原因处在顺序调用上,我刚才说了:父 Fragment总是优先于子 Fragment,而对于不可见事件,内部的 Fragment 生命周期总是先于外层 Fragment。回到我们代码里:父Fragment调用自身的 disPatchFragment方法分发了不可见事件,又会再次调用 dispatchChildFragmentVisibleState ,导致子 Fragment 再次调用自己的 disPatchFragment再次调用了一次 不可见事件onFragmentInVisible,故产生了两次。

解决办法就是我们之前定义的变量:currentVisibleState,如果当前的 Fragment 要分发的状态与 currentVisibleState 相同我们就没有必要去做分发了。

代码及添加位置如下:

``

8d1fe9ecb445

image.png

``

最后附上总代码,编写Fragment时,只需要继承该类,然后调用可见的方法就好了。

public abstract class BaseLazyLoadFragment extends Fragment {

View rootView;

/**当前Fragment是否首次可见,默认是首次可见**/

private boolean mIsFirstVisible = true;

/**当前Fragment的View是否已经创建**/

private boolean isViewCreated = false;

/**当前Fragment的可见状态,一种当前可见,一种当前不可见**/

private boolean currentVisibleState = false;

@Nullable

@Override

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

LogUtil.e(getClass().getSimpleName(),"-----> onCreateView");

if(rootView == null){

rootView = inflater.inflate(getLayoutId(), container, false);

initView(rootView);

}

isViewCreated=true;//在onCreateView执行完毕,将isViewCreated改为true;

return rootView;

}

@Override

public void setUserVisibleHint(boolean isVisibleToUser) {

super.setUserVisibleHint(isVisibleToUser);

if (isViewCreated) {

if (isVisibleToUser && !currentVisibleState) {//Fragment可见且状态不是可见(从一个Fragment切换到另外一个Fragment,后一个设置状态为可见)

disPatchFragment(true);

} else if (!isVisibleToUser && currentVisibleState) {//Fragment不可见且状态是可见(从一个Fragment切换到另外一个Fragment,前一个更改状态为不可见)

disPatchFragment(false);

}

}

}

/**返回子Fragment的布局id**/

public abstract int getLayoutId();

/**初始化View的方法**/

public abstract void initView(View rootView);

@Override

public void onStart() {

super.onStart();

//isHidden()是Fragment是否处于隐藏状态和isVisible()有区别

//getUserVisibleHint(),Fragement是否可见

if(!isHidden()&& getUserVisibleHint()){//如果Fragment没有隐藏且可见

//执行分发的方法,三种结果对应自Fragment的三个回调,对应的操作,Fragment首次加载,可见,不可见

disPatchFragment(true);

}

}

@Override

public void onResume() {

super.onResume();

if(!mIsFirstVisible){

//表示点击home键又返回操作,设置可见状态为ture

if(!isHidden()&& !getUserVisibleHint() && currentVisibleState){

disPatchFragment(true);

}

}

}

@Override

public void onPause() {

super.onPause();

//表示点击home键,原来可见的Fragment要走该方法,更改Fragment的状态为不可见

if(!isHidden()&& getUserVisibleHint()){

disPatchFragment(false);

}

}

@Override

public void onDestroyView() {

super.onDestroyView();

//当 View 被销毁的时候我们需要重新设置 isViewCreated mIsFirstVisible 的状态

isViewCreated = false;

mIsFirstVisible = true;

}

/**

*

* @param visible Fragment当前是否可见,然后调用相关方法

*/

public void disPatchFragment(boolean visible){

String aa =getClass().getSimpleName();

//如果父Fragment不可见,则不向下分发给子Fragment

if(visible && isParentFragmentVsible())return;

// 如果当前的 Fragment 要分发的状态与 currentVisibleState 相同(都为false)我们就没有必要去做分发了。

if (currentVisibleState == visible) {

return;

}

currentVisibleState=visible;

if(visible){//Fragment可见

if(mIsFirstVisible){//可见又是第一次

mIsFirstVisible=false;//改变首次可见的状态

onFragmentFirst();

}//可见但不是第一次

onFragmentVisble();

//可见状态的时候内层 fragment 生命周期晚于外层 所以在 onFragmentResume 后分发

dispatchChildFragmentVisibleState(true);

}else {//不可见

onFragmentInVisible();

dispatchChildFragmentVisibleState(false);

}

};

/**

* 重新分发给子Fragment

* @param visible

*/

private void dispatchChildFragmentVisibleState(boolean visible) {

FragmentManager childFragmentManager = getChildFragmentManager();

@SuppressLint("RestrictedApi") List fragments = childFragmentManager.getFragments();

if(fragments != null){

if (!fragments.isEmpty()) {

for (Fragment child : fragments) {

if (child instanceof BaseLazyLoadFragment && !child.isHidden() && child.getUserVisibleHint()) {

((BaseLazyLoadFragment) child).disPatchFragment(visible);

}

}

}

}

}

//Fragemnet首次可见的方法

public void onFragmentFirst(){

LogUtil.e(getClass().getSimpleName(),"首次可见");

};

//Fragemnet可见的方法

public void onFragmentVisble(){//子Fragment调用次方法,执行可见操作

LogUtil.e(getClass().getSimpleName(),"可见");

};

//Fragemnet不可见的方法

public void onFragmentInVisible(){

LogUtil.e(getClass().getSimpleName(),"不可见");

};

/**

*判断多层嵌套的父Fragment是否显示

*/

private boolean isParentFragmentVsible() {

BaseLazyLoadFragment fragment = (BaseLazyLoadFragment) getParentFragment();

return fragment != null && !fragment.getCurrentVisibleState();

}

private boolean getCurrentVisibleState() {

return currentVisibleState;

}

}

完毕!

相关文章:

  • android怎样拼接带参数的url,这种url网址如何拼接成android 的Retrofit注解
  • android:style/theme.holo.light,Galaxy Nexus上的Android Theme.Holo.Light在模拟器没有的时候有灰色背景...
  • 华为Android10版怎么截屏,华为Mate10怎么截屏?华为Mate10两种截图方法
  • solar2 android,Solar2(太阳系行星2)
  • 同一个页面显示多个html界面,浏览器怎么设置在同一个界面/窗口打开多个网页...
  • html中判断电话是否正确,jsjquery验证邮箱和手机号是否正确范例
  • 2021年高考成绩还能查询吗,【去年高考成绩还能查吗】_怎么查询以前的高考成绩往年高考成绩能查吗...
  • 电脑播放html5绿屏,我的电脑在看暴风影音时总是绿屏 是为什么啊?有什么解决良策啊?...
  • 使用计算机 发展了人的运算能力,计算机的发展
  • 皖西学院计算机网络期末试卷,皖西学院2013–2014学年度第1学期期末考试试卷(B卷)...
  • jq+设置html+值,jQuery 设置
  • 公共基础知识计算机考题,2017年全国计算机考试二级公共基础知识试题及答案...
  • 计算机专业未来美句,关于新的开始的句子
  • cortex a53 微型计算机,2019年值得期待的5个树莓派替代品
  • 计算机网络ch6网络层,(西南交大版)计算机网络作业CH6
  • .pyc 想到的一些问题
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • “大数据应用场景”之隔壁老王(连载四)
  • 【笔记】你不知道的JS读书笔记——Promise
  • Apache Spark Streaming 使用实例
  • CSS中外联样式表代表的含义
  • JavaScript学习总结——原型
  • React Native移动开发实战-3-实现页面间的数据传递
  • React16时代,该用什么姿势写 React ?
  • redis学习笔记(三):列表、集合、有序集合
  • RxJS: 简单入门
  • Vue2.x学习三:事件处理生命周期钩子
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 前端临床手札——文件上传
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • (4)logging(日志模块)
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (数据结构)顺序表的定义
  • (算法)Travel Information Center
  • (一)SpringBoot3---尚硅谷总结
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .Mobi域名介绍
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET Framework与.NET Framework SDK有什么不同?
  • .net 设置默认首页
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .net实现客户区延伸至至非客户区
  • .NET中 MVC 工厂模式浅析
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • /var/log/cvslog 太大
  • @autowired注解作用_Spring Boot进阶教程——注解大全(建议收藏!)
  • @Data注解的作用
  • [AX]AX2012开发新特性-禁止表或者表字段
  • [BZOJ5125]小Q的书架(决策单调性+分治DP+树状数组)
  • [CareerCup] 14.5 Object Reflection 对象反射