Android--Jetpack--Lifecycle详解

富贵本无根,尽从勤里得

一,定义

Lifecycle 是一个具备宿主生命周期感知能力的组件。它持有组件(Activity/Fragment)生命周期状态信息,并且允许其观察者监听宿主生命周期状态变化。

顾名思义,Lifecycle的主要作用其实就是帮助我们监听Activity或者Fragment的生命周期,不需要我们自己去定义回调接口来监听了,这样就使我们的代码更加简洁,逻辑更加清晰。

二,角色介绍

1,Lifecycle(生命周期) :一个核心抽象类,用于存储有关组件(如 activity/fragment )的生命周期状态的信息,并允许其他对象观察此状态。继承该类的子类,表示本身是一个 具有Android生命周期特性的对象。

2,LifecycleOwner:核心接口,Lifecycle 持有者,该接口的实现类表示能够为外部提供Lifecycle实例。具有 Android 生命周期的类。这些事件可以被自定义组件用来处理生命周期的变化,而不需要在 Activity/Fragment 中实现任何代码。

3,LifecycleRegistry:核心类,Lifecycle 的实现类,可以处理多个观察者。实现 Lifecycle 定义生命周期观察订阅,生命周期查询的方法。还实现了架构中,生命周期变化时触发的自身状态处理和相关对观察者的订阅回调的逻辑。

4,LifecycleObserver:观察者,将一个类标记为生命周期观察者。实现该接口的类,通过注解的方式,可以通过被 LifecycleOwner 类的 addObserver() 方法注册,LifecycleObserver 便可以观察到 LifecycleOwner 的生命周期事件。

5,State :当前生命周期所处的状态。

6,Event :当前生命周期改变对应的事件。从框架和 Lifecycle 类分派的生命周期事件。这些事件对应到 activity/fragment 中的回调事件。

三,基本使用

第一张使用方式非常简单:

1,添加依赖:

implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
implementation "androidx.lifecycle:lifecycle-common:2.5.1"

2,自定义一个类,这个类就是观察者,实现上面我们提到的LifecycleObserver 接口

定义方法,实现需要监控的生命周期,最主要的是注解

 @OnLifecycleEvent

以及上面提到的生命周期所处的状态:

public class YuanZhenLifecycleObserver implements LifecycleObserver {@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)void onCreate(){System.out.println("yz-----onCreate");}@OnLifecycleEvent(Lifecycle.Event.ON_START)void onStart(){System.out.println("yz-----onStart");}@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)void onResume(){System.out.println("yz-----onResume");}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)void onPause(){System.out.println("yz-----onPause");}@OnLifecycleEvent(Lifecycle.Event.ON_STOP)void onStop(){System.out.println("yz-----onStop");}@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)void onDestory(){System.out.println("yz-----onDestory");}}

 3,在需要被观察的宿主中,注册刚刚我们创建的观察者:

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getLifecycle().addObserver(new YuanZhenLifecycleObserver());View viewById = findViewById(R.id.txt);viewById.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Intent intent =new Intent(MainActivity.this,SecondActivity.class);startActivity(intent);finish();}});}}

SecondActivity代码如下:

public class SecondActivity extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);}
}

最后,运行后点击按钮,输出如下日志:

 至此,MainActivity的生命周期,就被我们轻松的观察到了。

第二种实现方式:

上一种实现方式方法已经过时了,所以我们推荐这种实现方式,直接实现接口DefaultLifecycleObserver 

然后我们重写它的生命周期方法即可:

public class YuanZhenFullObserver implements DefaultLifecycleObserver {@Overridepublic void onCreate(@NonNull LifecycleOwner owner) {DefaultLifecycleObserver.super.onCreate(owner);System.out.println("yz-----onCreate");}@Overridepublic void onStart(@NonNull LifecycleOwner owner) {DefaultLifecycleObserver.super.onStart(owner);System.out.println("yz-----onStart");}@Overridepublic void onResume(@NonNull LifecycleOwner owner) {DefaultLifecycleObserver.super.onResume(owner);System.out.println("yz-----onResume");}@Overridepublic void onPause(@NonNull LifecycleOwner owner) {DefaultLifecycleObserver.super.onPause(owner);System.out.println("yz-----onPause");}@Overridepublic void onStop(@NonNull LifecycleOwner owner) {DefaultLifecycleObserver.super.onStop(owner);System.out.println("yz-----onStop");}@Overridepublic void onDestroy(@NonNull LifecycleOwner owner) {DefaultLifecycleObserver.super.onDestroy(owner);System.out.println("yz-----onDestroy");}
}

然后再MainActivity使用:

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getLifecycle().addObserver(new YuanZhenFullObserver());View viewById = findViewById(R.id.txt);viewById.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Intent intent =new Intent(MainActivity.this,SecondActivity.class);startActivity(intent);finish();}});}}

运行后输出:

使用方式都非常的简单高效。

四,基本原理

从上面的使用中我们就可以看出,lifecycle显然是使用了观察者模式,如果对于观察者模式不清楚的,建议看下文章Android设计模式--观察者模式-CSDN博客

 我们看源码,只能是先从使用入手:

getLifecycle().addObserver(new YuanZhenFullObserver());

通过addObserver方法,我们找到了Lifecycle这个抽象类:

public abstract class Lifecycle {//使用的入口@MainThreadpublic abstract void addObserver(@NonNull LifecycleObserver observer);@MainThreadpublic abstract void removeObserver(@NonNull LifecycleObserver observer);。。。。}

它的实现类LifecycleRegistry 中addObserver方法:

@Override
public void addObserver(@NonNull LifecycleObserver observer) {enforceMainThreadIfNeeded("addObserver");//判断当前的生命周期,将当前生命周期保存State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;//将YuanZhenLifecycleObserver这个观察者对象保存起来ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);if (previous != null) {return;}//获取到当前的被观察者 也就是MainActivityLifecycleOwner lifecycleOwner = mLifecycleOwner.get();if (lifecycleOwner == null) {// it is null we should be destroyed. Fallback quicklyreturn;}boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;//计算当前生命周期State targetState = calculateTargetState(observer);mAddingObserverCounter++;while ((statefulObserver.mState.compareTo(targetState) < 0&& mObserverMap.contains(observer))) {pushParentState(statefulObserver.mState);final Event event = Event.upFrom(statefulObserver.mState);if (event == null) {throw new IllegalStateException("no event up from " + statefulObserver.mState);}statefulObserver.dispatchEvent(lifecycleOwner, event);popParentState();// mState / subling may have been changed recalculatetargetState = calculateTargetState(observer);}if (!isReentrance) {// we do sync only on the top level.sync();}mAddingObserverCounter--;
}

上面的 LifecycleOwner lifecycleOwner = mLifecycleOwner.get();是怎么来的呢?

再MainActivity中使用getLifecycle()方法,就进入到了它的父类ComponentActivity:

public class ComponentActivity extends androidx.core.app.ComponentActivity implementsContextAware,LifecycleOwner,ViewModelStoreOwner,HasDefaultViewModelProviderFactory,SavedStateRegistryOwner,OnBackPressedDispatcherOwner,ActivityResultRegistryOwner,ActivityResultCaller {//创建LifecycleRegistry 实例private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);//获取到创建的LifecycleRegistry 实例@NonNull@Overridepublic Lifecycle getLifecycle() {return mLifecycleRegistry;}@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {// Restore the Saved State first so that it is available to// OnContextAvailableListener instancesmSavedStateRegistryController.performRestore(savedInstanceState);mContextAwareHelper.dispatchOnContextAvailable(this);super.onCreate(savedInstanceState);//创建一个透明的fragmentReportFragment.injectIfNeededIn(this);if (mContentLayoutId != 0) {setContentView(mContentLayoutId);}}。。。。}

ComponentActivity实现了LifeCyclerOwern接口,在ComponentActivity这个类中,创建了LifecycleRegistry,并将它本省传递给了LifecycleRegistry。

在这个类的onCreate方法中,有一个非常重要的方法,ReportFragment.injectIfNeededIn(this);它创建了一个透明的fragment。我们看看这个fragment里面干了什么。

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
public class ReportFragment extends android.app.Fragment {private static final String REPORT_FRAGMENT_TAG = "androidx.lifecycle"+ ".LifecycleDispatcher.report_fragment_tag";public static void injectIfNeededIn(Activity activity) {if (Build.VERSION.SDK_INT >= 29) {//注册回调LifecycleCallbacks.registerIn(activity);}//绑定fragmentandroid.app.FragmentManager manager = activity.getFragmentManager();if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();manager.executePendingTransactions();}}@SuppressWarnings("deprecation")static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {if (activity instanceof LifecycleRegistryOwner) {//如果activity实现了LifecycleOwner接口 调用handleLifecycleEvent((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);return;}if (activity instanceof LifecycleOwner) {Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();if (lifecycle instanceof LifecycleRegistry) {((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);}}}static ReportFragment get(Activity activity) {return (ReportFragment) activity.getFragmentManager().findFragmentByTag(REPORT_FRAGMENT_TAG);}private ActivityInitializationListener mProcessListener;private void dispatchCreate(ActivityInitializationListener listener) {if (listener != null) {listener.onCreate();}}private void dispatchStart(ActivityInitializationListener listener) {if (listener != null) {listener.onStart();}}private void dispatchResume(ActivityInitializationListener listener) {if (listener != null) {listener.onResume();}}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);dispatchCreate(mProcessListener);dispatch(Lifecycle.Event.ON_CREATE);}@Overridepublic void onStart() {super.onStart();dispatchStart(mProcessListener);dispatch(Lifecycle.Event.ON_START);}@Overridepublic void onResume() {super.onResume();dispatchResume(mProcessListener);dispatch(Lifecycle.Event.ON_RESUME);}@Overridepublic void onPause() {super.onPause();dispatch(Lifecycle.Event.ON_PAUSE);}@Overridepublic void onStop() {super.onStop();dispatch(Lifecycle.Event.ON_STOP);}@Overridepublic void onDestroy() {super.onDestroy();dispatch(Lifecycle.Event.ON_DESTROY);// just want to be sure that we won't leak reference to an activitymProcessListener = null;}private void dispatch(@NonNull Lifecycle.Event event) {if (Build.VERSION.SDK_INT < 29) {// Only dispatch events from ReportFragment on API levels prior// to API 29. On API 29+, this is handled by the ActivityLifecycleCallbacks// added in ReportFragment.injectIfNeededIndispatch(getActivity(), event);}}void setProcessListener(ActivityInitializationListener processListener) {mProcessListener = processListener;}interface ActivityInitializationListener {void onCreate();void onStart();void onResume();}// this class isn't inlined only because we need to add a proguard rule for it (b/142778206)// In addition to that registerIn method allows to avoid class verification failure,// because registerActivityLifecycleCallbacks is available only since api 29.@RequiresApi(29)static class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {static void registerIn(Activity activity) {activity.registerActivityLifecycleCallbacks(new LifecycleCallbacks());}@Overridepublic void onActivityCreated(@NonNull Activity activity,@Nullable Bundle bundle) {}@Overridepublic void onActivityPostCreated(@NonNull Activity activity,@Nullable Bundle savedInstanceState) {dispatch(activity, Lifecycle.Event.ON_CREATE);}@Overridepublic void onActivityStarted(@NonNull Activity activity) {}@Overridepublic void onActivityPostStarted(@NonNull Activity activity) {dispatch(activity, Lifecycle.Event.ON_START);}@Overridepublic void onActivityResumed(@NonNull Activity activity) {}@Overridepublic void onActivityPostResumed(@NonNull Activity activity) {dispatch(activity, Lifecycle.Event.ON_RESUME);}@Overridepublic void onActivityPrePaused(@NonNull Activity activity) {dispatch(activity, Lifecycle.Event.ON_PAUSE);}@Overridepublic void onActivityPaused(@NonNull Activity activity) {}@Overridepublic void onActivityPreStopped(@NonNull Activity activity) {dispatch(activity, Lifecycle.Event.ON_STOP);}@Overridepublic void onActivityStopped(@NonNull Activity activity) {}@Overridepublic void onActivitySaveInstanceState(@NonNull Activity activity,@NonNull Bundle bundle) {}@Overridepublic void onActivityPreDestroyed(@NonNull Activity activity) {dispatch(activity, Lifecycle.Event.ON_DESTROY);}@Overridepublic void onActivityDestroyed(@NonNull Activity activity) {}}
}

从这个fragment中我们可以看出,ReportFragment的生命周期函数都调用了dispatch()方法,而dispatch()方法则会判断Activity是否实现了LifecycleOwner接口,如果实现了该接口就调用LifecycleRegister的handleLifecycleEvent()。再来看看handleLifecycleEvent:

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {enforceMainThreadIfNeeded("handleLifecycleEvent");moveToState(event.getTargetState());
}
private void moveToState(State next) {if (mState == next) {return;}if (mState == INITIALIZED && next == DESTROYED) {throw new IllegalStateException("no event down from " + mState);}mState = next;if (mHandlingEvent || mAddingObserverCounter != 0) {mNewEventOccurred = true;// we will figure out what to do on upper level.return;}mHandlingEvent = true;sync();mHandlingEvent = false;if (mState == DESTROYED) {mObserverMap = new FastSafeIterableMap<>();}
}private void sync() {LifecycleOwner lifecycleOwner = mLifecycleOwner.get();if (lifecycleOwner == null) {throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"+ "garbage collected. It is too late to change lifecycle state.");}while (!isSynced()) {mNewEventOccurred = false;// no need to check eldest for nullability, because isSynced does it for us.if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {backwardPass(lifecycleOwner);}Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();if (!mNewEventOccurred && newest != null&& mState.compareTo(newest.getValue().mState) > 0) {forwardPass(lifecycleOwner);}}mNewEventOccurred = false;
}

事件发生的时候,先得到当前activity应该出现的下一个状态,

moveToState(next); mState = next;更新现在的状态

sync();

backwardPass(lifecycleOwner);逆推

forwardPass(lifecycleOwner);正推

看看这两个方法:

private void forwardPass(LifecycleOwner lifecycleOwner) {Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =mObserverMap.iteratorWithAdditions();while (ascendingIterator.hasNext() && !mNewEventOccurred) {Map.Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();ObserverWithState observer = entry.getValue();while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred&& mObserverMap.contains(entry.getKey()))) {pushParentState(observer.mState);final Event event = Event.upFrom(observer.mState);if (event == null) {throw new IllegalStateException("no event up from " + observer.mState);}observer.dispatchEvent(lifecycleOwner, event);popParentState();}}
}
private void backwardPass(LifecycleOwner lifecycleOwner) {Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> descendingIterator =mObserverMap.descendingIterator();while (descendingIterator.hasNext() && !mNewEventOccurred) {Map.Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();ObserverWithState observer = entry.getValue();while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred&& mObserverMap.contains(entry.getKey()))) {Event event = Event.downFrom(observer.mState);if (event == null) {throw new IllegalStateException("no event down from " + observer.mState);}pushParentState(event.getTargetState());observer.dispatchEvent(lifecycleOwner, event);popParentState();}}
}

大致原理请看下图:

然后就调用 observer.dispatchEvent(lifecycleOwner, event); 生成观察者适配器:

static class ObserverWithState {State mState;LifecycleEventObserver mLifecycleObserver;ObserverWithState(LifecycleObserver observer, State initialState) {//创建观察者adapter 并将观察者传入adapter mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);mState = initialState;}void dispatchEvent(LifecycleOwner owner, Event event) {State newState = event.getTargetState();mState = min(mState, newState);mLifecycleObserver.onStateChanged(owner, event);mState = newState;}
}

mLifecycleObserver.onStateChanged(owner, event);将状态的变化通知给了观察者,来看看具体实现:

class FullLifecycleObserverAdapter implements LifecycleEventObserver {private final FullLifecycleObserver mFullLifecycleObserver;private final LifecycleEventObserver mLifecycleEventObserver;FullLifecycleObserverAdapter(FullLifecycleObserver fullLifecycleObserver,LifecycleEventObserver lifecycleEventObserver) {mFullLifecycleObserver = fullLifecycleObserver;mLifecycleEventObserver = lifecycleEventObserver;}@Overridepublic void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {switch (event) {case ON_CREATE:mFullLifecycleObserver.onCreate(source);break;case ON_START:mFullLifecycleObserver.onStart(source);break;case ON_RESUME:mFullLifecycleObserver.onResume(source);break;case ON_PAUSE:mFullLifecycleObserver.onPause(source);break;case ON_STOP:mFullLifecycleObserver.onStop(source);break;case ON_DESTROY:mFullLifecycleObserver.onDestroy(source);break;case ON_ANY:throw new IllegalArgumentException("ON_ANY must not been send by anybody");}if (mLifecycleEventObserver != null) {mLifecycleEventObserver.onStateChanged(source, event);}}
}

FullLifecycleObserverAdapter 在创建时,会持有LifecycleOwner ,当调用onStateChanged时,会调用具体观察者LifecycleOwner 的具体生命周期方法。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【3DsMax】制作简单的骨骼动画

效果 步骤 首先准备4个板子模型展开放置好 添加一个4段的骨骼 选中其中的一块板子添加蒙皮命令 在蒙皮的参数面板中&#xff0c;设置每块板子对应哪块骨骼 设置好后你可以发现此时就已经可以通过骨骼来控制模型了 接下来就可以制作动画 点击左下角“时间配置”按钮 设置一下动…

网络程序设计

互相连接&#xff0c;发送信息 tcp和udp协议 tcp会有准备&#xff0c;udp不会准备。 8080端口&#xff1a;tomcat端口&#xff0c;java和web相连接 80端口&#xff1a;http 21端口&#xff1a;ftp 套接字 socket&#xff1a;提供给程序可以对外进行连接的接口 ip地址 …

Elk:filebeat 日志收集工具和logstash

Filebeat是一个轻量级的日志收集工具,所使用的系统资源比logstash部署和启动时使用的资源要小得多 Filebeat可以在非java环境使用&#xff0c;他可以代理logstash在非java环境上收集日志 缺点Filebeat无法实现数据的过滤,一般是结合logstash的 实验 ELK 企业级日志分析系统---…

Java第二十一章网络通信

一、网络程序设计基础 1、局域网与互联网 为了实现两台计算机的通信&#xff0c;必须用一个网络线路连接两台计算机&#xff0c;如下图所示。 2、网络协议 1.IP协议 IP指网际互连协议&#xff0c;Internet Protocol的缩写&#xff0c;是TCP/IP体系中的网络层协议。设计IP的目的…

C++ 拷贝构造函数

目录 拷贝构造函数概述 拷贝构造函数特性 拷贝构造函数概述 当我们定义好一个类&#xff0c;不做任何处理时&#xff0c;编译器会自动生成以下6个默认成员函数&#xff1a; 默认成员函数&#xff1a;如果用户没有手动实现&#xff0c;则编译器会自动生成的成员函数。 同样&…

Centos图形化界面封装OpenStack Ubuntu镜像

目录 背景 环境 搭建kvm环境 安装ubuntu虚机 虚机设置 系统安装 登录虚机 安装cloud-init 安装cloud-utils-growpart 关闭实例 删除细节信息 删除网卡细节 使虚机脱离libvirt纳管 结束与验证 压缩与转移 验证是否能够正常运行 背景 一般的镜像文件在上传OpenSt…

DBSCAN聚类算法学习笔记

DBSCAN聚类算法学习笔记 一些概念名词 MinPts&#xff1a;聚类在一起的点的最小数目&#xff0c;超过这一阈值才算是一个族群 核心点&#xff1a;邻域内数据点超过MinPts的点 边界点&#xff1a;落在核心点邻域内的点称为边界点 噪声点&#xff1a;既不是核心点也不是边界点的…

校园教务管理系统

学年论文&#xff08;课程设计&#xff09; 题目&#xff1a; 信息管理系统 校园教务管理系统 摘要&#xff1a;数据库技术是现代信息科学与技术的重要组成部分&#xff0c;是计算机数据处理与信息管理系统的核心&#xff0c;随着计算机技术的发展&#xff0c;数据库技…

OCP Java17 SE Developers 复习题08

答案 答案 答案 A. This code is correct. Line 8 creates a lambda expression that checks whether the age is less than 5, making option A correct. Since there is only one parameter and it does not specify a type, the parentheses around the parameter are …

h5如何跳转到微信公众号中

需求&#xff1a;点击按钮或者某个地方&#xff0c;弹出关注公众号的页面。&#xff08;h5跳转到微信公众号&#xff09; 需要什么&#xff1a;通过window.location.href来进行跳转。 因此&#xff0c;需要一个微信公众号链接。 一、打开想要跳转到的微信公众号的任何一篇文章&…

单片机_RTOS_架构

一. RTOS的概念 // 经典单片机程序 void main() {while (1){喂一口饭();回一个信息();} } ------------------------------------------------------ // RTOS程序 喂饭() {while (1){喂一口饭();} }回信息() {while (1){回一个信息();} }void main() {create_task(喂饭);cr…

一网打尽损失函数和正则化的关系,在损失函数中加入正则化有什么用,如何加入,这里为大家用通俗易懂的例子进行详细解释!(系列1)

文章目录 一、BP神经网络预测中&#xff0c;常见的损失函数是均方误差损失函数MSE二、L2正则化的公式如下&#xff1a;三、 结合MSE和L2正则化的总损失函数公式如下&#xff1a;总结 一、BP神经网络预测中&#xff0c;常见的损失函数是均方误差损失函数MSE 在BP神经网络预测中…

气膜厂家怎样确保产品质量和售后服务?

气膜厂家作为一家专业生产气膜产品的企业&#xff0c;确保产品质量和提供良好的售后服务是我们的责任和使命。为了确保产品质量和售后服务的可靠性&#xff0c;我们采取了以下措施。 起初&#xff0c;我们严格按照国家标准和相关行业规范进行生产。气膜产品的质量是产品能否长…

【JavaEE进阶】 Spring 的创建和使⽤

文章目录 &#x1f334;前言&#x1f38b;创建 Spring 项⽬&#x1f6a9;创建⼀个 Maven 项⽬&#x1f6a9;添加 Spring 框架⽀持&#x1f6a9;添加启动类 &#x1f333;存储 Bean 对象&#x1f6a9;创建Bean&#x1f6a9;将 Bean 注册到容器 &#x1f332;获取并使⽤ Bean 对象…

图解系列--Web服务器,Http首部

1.用单台虚拟主机实现多个域名 HTTP/1.1 规范允许一台 HTTP 服务器搭建多个 Web 站点。。比如&#xff0c;提供 Web 托管服务&#xff08;Web Hosting Service&#xff09;的供应商&#xff0c;可以用一台服务器为多位客户服务&#xff0c;也可以以每位客户持有的域名运行各自不…

VSCode之C++ CUDA入门:reduce的N+1重境界

背景 Reduce是几乎所有多线程技术的基础和关键&#xff0c;同样也是诸如深度学习等领域的核心&#xff0c;简单如卷积运算&#xff0c;复杂如梯度聚合、分布式训练等&#xff0c;了解CUDA实现reduce&#xff0c;以及优化reduce是理解CUDA软硬件连接点的很好切入点。 硬件环境&…

模式识别与机器学习(七):集成学习

集成学习 1.概念1.1 类型1.2 集成策略1.3 优势 2. 代码实例2.1boosting2.2 bagging2.3 集成 1.概念 集成学习是一种机器学习方法&#xff0c;旨在通过组合多个个体学习器的预测结果来提高整体的预测性能。它通过将多个弱学习器&#xff08;个体学习器&#xff09;组合成一个强学…

空间金字塔池化(SPP,Spatial Pyramid Pooling)系列

空间金字塔池化的作用是解决输入图片大小不一造成的缺陷&#xff0c;同时在目标识别中增加了精度。空间金字塔池化可以使得任意大小的特征图都能够转换成固定大小的特征向量&#xff0c;下面针对一些典型的空间金字塔进行盘点。 部分图片来自blog:空间金字塔池化改进 SPP / SP…

Jmeter接口自动化测试 —— Jmeter断言之Json断言

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

PHP:js中怎么使用PHP变量,php变量为数组时的处理

方法一&#xff1a;使用内嵌 PHP 脚本标记 1、简单的拼接 使用内嵌的 PHP 脚本标记 <?php ?> 将 PHP 变量 $phpVariable 的值嵌入到 JavaScript 代码中。 <?php $phpVariable "Hello, World!"; ?><script> // 将 PHP 变量的值传递给 JavaS…