FyListen——生命周期监听器(设计原理之理解生命周期)

news2024/12/24 9:22:57

FyListen——生命周期监听器(设计原理之理解生命周期)

FyListen 的核心原理有两个:

  1. 通过子Fragment对Activity、Fragment进行生命周期监听
  2. Java8 接口特性 default

1. 什么是上下文Context

请添加图片描述

这是一个装饰器模式, ContextImpl 是 Context 的基础实现类, ContextWrapper 是对 ContextImpl 的包装类。ContextThemeWrapper 是对装饰器的再装饰,又增加了一些功能。

1.1 如何获取 Context?

获取 Context 的方法有很多:getContext(), getBaseContext(), getApplication(), getApplicationContext()。我们来看一下他们的区别:

getApplication()和 getApplicationContext() 获取到的就是同一个对象,只是使用的范围不一样:

  • getApplication() 只有 Activity 和 Service 才有。
  • 想要在其他地方获取 Application 只能通过 getApplicationContext().

getContext(), getBaseContext()和 getApplicationContext() 有什么区别?

  • Activity,Service 和 Application 都有 getBaseContext(),getApplicationContext() 这两个方法,但没有 getContext() 方法。

  • getContext() 方法只有在 Fragment 中才有,获取的是寄主对象,也就是 Activity。

    所以 Fragment 必须依赖于 Activity 存在

1.2 Application 有什么用?

Application 是全局单例,可以通过 getApplication() 和 getApplicationContext() 获取。

需要注意的是,如果在 application 中调用 context 的方法,必须在 attachBaseContext() 之后,在此之前 context 是没有赋值的。

2. Activity 与 Fragment 生命周期绑定原理

先来看一张Fragment状态转移图:(图来自稀土掘金)

img

这张图的解读可以看到下面这张表,Activity 管理 Fragment 生命周期的方式是在 Activity 的生命周期方法中调用 FragmentManager 的对应方法,通过 FragmentManager 将现有的 Fragment 迁移到下一个状态,同时触发相应的生命周期函数:

Activity生命周期函数FragmentManager触发的方法Fragmet你状态转移Fragment生命周期回调
onCreate()dispatchCreateINITIALIZING->CREATEDonAttach()、onCreate()
dispatchActivityCreated()CREATED->ACTIVITY_CREATEDonCreateView()、onActivityCreated()、
onStart()dispatchStartACTIVITY_CREATED->STARTEDonStart()
onResume()dispatchResumeSTARTED->RESUMEDonResume()
onPausedispatchPauseRESUMED->STARTEDonPause()
onStopdispatchStopSTARTED->STOPPEDonStop()
onDestroydispatchDestroySTOPPED->ACTIVITY_CREATED->CREATED->CREATED->INITIALIZINGonDestroyView()、onDestroy()、onDetach()

我们从源码角度来看一下是如何绑定的生命周期,首先我们需要知道,Activity 生命周期是由 AMS(ActivityManagerService)管理、回调的,这部分请大家在 AMS 专题学习。便于理解,我们提前看到源码中关于Fragment的状态转移代码处理:

需要提醒的Java基础是,switch: 一旦switch表达式与某个case分支匹配,则从该分支的语句开始执行,一致执行下去!其后所有case分支的语句也会被执行,直到遇到break语句!!!

//[FragmentManager.java]
void moveToState(Fragment f, int newState, int transit, int transitionStyle,boolean keepActive) {
    //newState是Fragment将要被转移到的状态state
    //f.mState是Fragment现有的状态state
    if(f.mState <= newState){
        switch(f.mState){
            case Fragment.INITIALIZING://Fragment当前状态还在INITIALIZINGActivity调用了onCreate(),newState是CREATEDFragment进行状态转移
                if(newState > Fragment.INITIALIZING){
					f.onAttach();
                    dispatchOnFragmentAttached();
                    if(!f.mIsCreated){
                        //如果fragment还没create()
                        f.performCreate();
                        dispatchOnFragmentCreated();
                    }else{
                        //如果fragment过去已经create()过了,只不过是detach()了,并没有销毁。也就是这个Fragment虽然生命结束了,但后来又被加载使用了(复用了)
                        f.mState = Fragment.CREATED;
                    }
                }
            case Fragment.CREATED:
                if(newState > Fragment.CREATED){//Fragment当前状态在CREATED,但Activity紧接着又将状态调整为ACTIVITY_CREATED,Fragment进行状态转移
					f.mView = f.performCreateView();
                    if(f.mView!=null){
                        //如果没有view,就不往它的子Fragment进行生命周期回调分发了
                        dispatchOnFragmentViewCreated();
                    }
                    f.performActivityCreated();
                    dispatchOnFragmentActivityCreated();
                }
                
            case Fragment.ACTIVITY_CREATED:
                
                if(newState > Fragment.ACTIVITY_CREATED){
                    //只进行状态转移
                    f.mState = Fragment.STOPPED;
                }
            case Fragment.STOPPED:
                if(newState > Fragment.STOPPED){
                    f.performStart();
                    dispatchOnFragmentStarted();
                }
            case Fragment.STARTED:
                if(newState > Fragment.STARTED){
                    f.performResume();
                    dispatchOnFragmentResumed();
                }
        }
    }else if(f.mState > newState){
        //反向转移
        switch(f.mState){
            case Fragment.RESUMED:
                if(newState < Fragment.RESUMED){
                    f.performPause();
                    dispatchOnFragmentPaused();
                }
            case Fragment.STARTED:
                if(newState < Fragment.STARTED){
                    f.performStop();
                    dispatchOnFragmentStopped();
                }
            case Fragment.STOPPED:
            case Fragment.ACTIVITY_CREATED:
                if(newState < Fragment.ACTIVITY_CREATED){
                    f.performDestroyView();
                    dispatchOnFragmentViewDestroyed();
                }
            case Fragment.CREATED:
                if(newState < Fragment.CREATED){
                    f.performDestroy();
                    dispatchOnFragmentDestroy();
                }
                f.performDetach();
                dispatchOnFragmentDetached();
        }
        if(f.mState != newState){
            f.mState = newState;
        }
    }
}

我们了解了 Fragment 的生命周期是由于 Activity 生命周期的回调,设定了 Fragment 应当到的 newState,然后让 Fragment 进行状态转移,转移的过程中回调 Fragment 的生命周期。所以我们主要需要看 Activity 是如何设置 newState 的。从 AMS 回调 Activity 的 performXXX() 看起:

2.1 AMS->Activity.performCreate()

  1. 在 Activity 的 onCreate() 中将 Fragment 的状态转移目标 newState 设置为了 CREATED,状态转移期间回调了Fragment的 onAttach() 和 onCreate()
  2. performCreate()又将 Fragment 的状态转移目标newState设置为了 ACTIVITY_CREATED,Fragment在状态转移期间回调了Fragment的 onCreateView() 和 onActivityCreate()
//[Activity.java]
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    //调用Activity的onCreate()方法,其中回调了Fragment的onAttach()和onCreate()方法
    if (persistentState != null) {
        onCreate(icicle, persistentState);
    } else {
        onCreate(icicle);
    }
    //调用到moveToState,且newState为Fragment.ACTIVITY_CREATED,状态转移过程中,回调了Fragment的onCreateView()和onActivityCreate().
    mFragments.dispatchActivityCreated();
}

protected void onCreate(@Nullable Bundle savedInstanceState) {
    //调用到moveToState,且newState为Fragment.CREATED,在状态转移期间回调了Fragment的onAttach()和onCreate()方法
    mFragments.dispatchCreate();
    //Application的Lifecycle回调
    dispatchActivityCreated(savedInstanceState);
}

2.2 AMS->performStart()

  1. 调用了 Activity 的 onStart()
  2. 将Fragment的状态转移目标newState设置为了STARTED,Fragment在期间回调了Fragment的 onStart() 方法
//[Activity.java]
final void performStart(String reason){
    //回调了 activity.onStart(),其中进行Application的Lifecycle回调
    mInstrumentation.callActivityOnStart(this);
    //调用到moveToState,且newState为Fragment.STARTED,其中回调了onStart()方法。虽然在switch中将Fragment的状态停留在了STOPPED,但在moveToState()方法的最后,又将Fragment的状态设置到了STARTED。
    mFragments.dispatchStart()
}

2.3 AMS->performResume()

  1. 调用了 Activity 的 onResume()
  2. 将Fragment的状态转移目标newState设置为了RESUMED,Fragment在状态转移期间回调了Fragment的 onResume();
//[Activity.java]
final void performResume(boolean followedByPause, String reason){
    //如果activity之前不是started的,会进入此方法,确保将activity变为start
    performRestart(true,reason);
    //如果activity之前是start的:
    //回调activity.onResume(),里面回调了 Application的Lifecycle
    mInstrumentation.callActivityOnResume(this);
    //调用到moveToState,且newState为Fragment.RESUMED,状态转移期间回调了Fragment的onResume()方法
    mFragments.dispatchResume();
}

2.4 AMS->performPause()

【注意!!!】我们发现,从这里开始,是先从Fragment开始状态转换,而且是往回转移,newState<f.mState,然后才调用Activity的生命周期回调

  1. 注意,状态转移设为newState=STARTED,开始往回转移!!!
  2. Fragment状态转移期间回调了onPause()方法
  3. 然后才调用Activity的onPause()方法
//[Activity.java]
final void performPause(boolean preserveWindow, String reason) {
    //在此之前状态为RESUMED,由于f.mState<newState,将进行往回状态转移!
    //Fragment状态转移到STARTED期间回调了Fragment的onPause()
    mFragments.dispatchPause();
    //调用Activity的onPause(),同时回调Application的Lifecycle
    onPause();
}

2.5 AMS->performStop()

【注意!!!】先从Fragment开始状态转换,而且是往回转移,newState<f.mState,然后才调用Activity的生命周期回调

  1. 注意,状态转移目标设为newState = STOPPED,往回状态转移
  2. Fragment状态转移期间回调了 onStop()方法
  3. 然后才调用Activity的onStop()方法
//[Activity.java]
final void performStop(boolean preserveWindow, String reason) {
    //Fragment状态转移到STOPPED,往回状态转移期间,回调了Fragment的onStop()方法
    mFragments.dispatchStop();
    //其中回调了Activity的onStop(),同时回调Application中的监听Lifecycle
    mInstrumentation.callActivityOnStop(this);
}

2.6 AMS->performRestart()

Activity可能会在onStop()之后又onRestart(),需要注意的是,这里并没有回调Fragment的生命周期,只调用了activity的onRestart(),并调用performStart(),后续的生命周期回调就和onStart()之后的一致了

//[Activity.java]
final void performRestart(boolean start, String reason) {
    //先判断之前是否为Stop状态
    if(mStopped){
        mStopped = false;
        //调用Activity的onRestart()回调
        mInstrumentation.callActivityOnRestart(this);
        //里面调用了Activity的onStart(),并进行Fragment状态转移与生命周期回调
        performStart();
    }
}

final void performStart(String reason) {
    //调用Activity.onStart(),并回调Application的Lifecycle,通知Application这个activity的生命周期现状
    mInstrumentation.callActivityOnStart(this);
    //newState=STARTED,Fragment状态从STOPPED到STARTED状态转移,期间回调了Fragment的onStart()
    mFragments.dispatchStart();
}

2.7 AMS->performDestroy()

【注意!!!】先从Fragment开始状态转换,而且是往回转移,newState<f.mState,然后才调用Activity的生命周期回调

  1. 先进行Fragment状态转移,newState=INITIALIZING,期间回调了Fragment的onDestroyView,onDestroy,onDetach
  2. Fragment状态转移完成,才进行Activity的onDestroy()
//[Activity.java]
final void performDestroy(){
    //先进行Fragment状态转移,newState=INITIALIZING,期间回调了Fragment的onDestroyView,onDestroy,onDetach
    mFragments.dispatchDestroy();
    //Fragment状态转移完成,才进行Activity的onDestroy()
    onDestroy();
}

我们回到 moveToState 来看一下是怎么连着回调三个Fragment生命周期的,需要注意,此时f.mState = STOPPED,newState=INITIALIZING:

需要提醒的Java基础是,switch: 一旦switch表达式与某个case分支匹配,则从该分支的语句开始执行,一致执行下去!其后所有case分支的语句也会被执行,直到遇到break语句!!!

//[FragmentManager.java]
void moveToState(Fragment f, int newState, int transit, int transitionStyle,boolean keepActive) {
    if(f.mState 《= newState){
        //...
    }else if(f.mState > newState){
        switch(f.mState){
            //...
            case Fragment.STOPPED://分支判断成功,继续执行后续case分支语句,直到遇到break
            case Fragment.ACTIVITY_CREATE:
                if(newState < Fragment.ACTIVITY_CREATED){
                    //1. 回调Fragment的onDestroyView()
                    f.performDestroyView();
                    //把该事件也分发给f的子Fragment
                    dispatchOnFragmentViewDestroyed();
                }
            case Fragment.CREATED:
                if(newState < Fragment.ACTIVITY_CREATED){
                    //2. 回调Fragment的onDestroy()
                    f.performDestroy();
                    //把该事件也分发给f的子Fragment
                    dispatchOnFragmentDestroyed();
                    //3. 回调Fragment的onDetach()
                    f.performDetach();
                    //把该事件也分发给f的子Fragment
                    dispatchOnFragmentDetached();  
                }
                //switch end
        }
    }
    //状态转移完成,最终更新f.mState = INITIALIZING
    if(f.mState != newState){
        f.mState = newState;
    }
}

至此,我们分析完了生命周期回调。如果你比较细心,会发现这里除了处理fragment的生命周期,还有的时候会处理fragment的动画和view的显示。

2. 补充:Fragment生命周期除了自动由 Activity 来回调,也可以由用户操控 FragmentTansaction 进行 Fragment 的调度时候回调生命周期:

先来看这张图:(图源稀土掘金)

img

我们经常使用 FragmentTransaction 中的 add()、remove()、replace()、attach()、detach()、hide()、show() 等方法对 Fragment进行操作,这些方法都会使 Fragment 的状态发生变化,出发对应的生命周期函数。默认 Activity 处于 Resume 状态:

  • add/remove 操作会引起 Fragment 在 INITIALIZING 和 RESUMED 这两个状态之间迁移
  • attach/detach操作会引起 Fragment 在 CREATED 和 RESUMED 两个状态之间迁移

add() 需要注意的是,如果Activity处于 STARTED 状态,Fragment 是无法进入 RESUMED 状态的,只有当 Activity 进入 RESUME 状态才会通知 Fragment 进入 RESUMED。

hide/show方法内部其实调用了 FragmentTransaction 的add/remove 方法。

3. Fragment 与 子Fragment 生命周期绑定原理

我们观察到 Fragment 中也持有一个 FragmentManager:mChildFragmentManage 用于管理子Fragment。所以在生命周期事件分发过程中,会呈树形结构向所有子Fragment进行分发:

//[Fragment.java]
public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListener {
    //上层管理当前Fragment的FragmentManager
    FragmentManagerImpl mFragmentManager;
    //当前Fragment用于管理子Fragment的fm,在生命周期回调中,会同时分发给 MChildFragmentManager 中的所有子Fragment
    FragmentManagerImpl mChildFragmentManager;
    //所属的父Fragment
    Fragment mParentFragment;
}


FragmentManager 中管理着 Fragments:mAdds 和 mActive:

//[FragmentManager.java]
final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
    //当前活跃的Fragment
    SparseArray<Fragment> mActive;
    //所有已添加的Fragment
    final ArrayList<Fragment> mAdded = new ArrayList<>();
    //管理的其他信息
    ArrayList<BackStackRecord> mBackStack;
    ArrayList<Fragment> mCreatedMenus;
    //...
        
    //分发生命周期:以dispatchResume()为例
    public void dispatchResume(){
        mStateSaved = false;
        //进行Fragment的状态转移
        dispatchMoveToState(Fragment.RESUMED);
    }
    //其中通过moveToState先进行预处理,即找到所有当前FragmentManager所管理的Fragment进行逐个事件分发
    private void dispatchMoveToState(int state) {
        if (mAllowOldReentrantBehavior) {
            moveToState(state, false);
        } else {
            try {
                mExecutingActions = true;
                moveToState(state, false);
            } finally {
                mExecutingActions = false;
            }
        }
        execPendingActions();
    }
    
    //拿到 mAdds 和 mActive 中的Fragment去分发事件(逐个让他们去进行状态转移)
    //注意这个是两个参数的 moveToState(),真正状态转移的moveToState()方法是四个参数的,注意区分
    void moveToState(int newState,boolean always){
        if (mActive != null) {
            final int numAdded = mAdded.size();
            for (int i = 0; i < numAdded; i++) {
                Fragment f = mAdded.get(i);
                //逐个fragment进行状态转移
                moveFragmentToExpectedState(f);
            }
            final int numActive = mActive.size();
            for (int i = 0; i < numActive; i++) {
                Fragment f = mActive.valueAt(i);
                if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) {
                    //逐个fragment进行状态转移
                    moveFragmentToExpectedState(f);
                }
            }
        }
    }
    
    //moveFragmentToExceptedState()通过四个参数的moveToState()让fragment进行状态转移
    void moveFragmentToExceptedState(final Fragment f){
        int nextState = mCurState;//新状态被标记在成员变量,不作为参数传入,简化代码
        //进行状态转移,具体的我们之前已经看过了
        moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
    }
    
}

4. Activity与Fragment的树形结构

既然我们已经知道了 Fragment 的生命周期可以由 Activity 或者 Fragment 进行回调,那么我们就可以通过这个特性进行 Activity 或者 父Fragment生命周期的监听!!!主流框架 Glide 中生命周期监听的方式,也是利用了这个特性。我画了两张图,大家先感性地认知一下 Fragment 监听 Activity 生命周期的构造:

Activity与Fragment的树形结构:

请添加图片描述

我们可以看到,这是一个可以找到父节点的多叉树。

fragment想要与Activity通信可以通过Fragment中的 FragmentHostCallback类型对象mHost:里面存了Fragment所依存的Activity实例、主线程Handler。Fragment中启动Activity,也是通过这个对象,让上层去执行启动Activity的请求。

5. 使用 Java8 接口特性 default 进行外观设计

java8 之前,往接口里新加一个方法,那么所有的实现类都需要变动,都需要同步实现这个方法。
java8 给接口新增了两个关键字:default static
使得可以往接口里添加默认方法,子类可以无需变动。

同时,这也使得接口中的方法并不需要全都实现,只需要重写需要的方法即可!

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

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

相关文章

【ChatGPT说】我想给大家【编】一个故事,故事的主人公叫【架构师李肯】,故事的开头,还得从他那年买房说起。。。

大家好啊&#xff0c;我就是那个【天涯何处无知己&#xff0c;人穷陌路勿担忧】的架构师李肯&#xff01; 架构师李肯&#xff08;全网同名&#xff09; 在深圳白手起家&#xff0c;毕业不到4年实现一线城市核心地段的安家梦&#xff0c;从0开始谱写励志人生&#xff01;一个专…

一文手把手教你写一个 Makefile 文件

如果我们是在Linux下开发&#xff0c;那Makefile肯定要知道&#xff0c;不懂Makefile&#xff0c;面对较大的工程项目的时候就会比较麻烦&#xff0c;懂得利用开发工具将会大大提高我们的开发效率&#xff0c;也可以说Makefile是必须掌握的一项技能。 一、了解什么是 Makefile…

java集合框架内容整理

主要内容集合框架体系ArrayListLinkedListHashSetTreeSetLinkedHashSet内部比较器和外部比较器哈希表的原理List集合List集合的主要实现类有ArrayList和LinkedList&#xff0c;分别是数据结构中顺序表和链表的实现。另外还包括栈和队列的实现类&#xff1a;Deque和Queue。• Li…

steam/csgo搬砖项目真能月入过万吗?到底真的假的?

提前说明&#xff0c;这是正经、真实、官方渠道的兼职赚钱方式&#xff0c;不需要学历、不需要人脉&#xff0c;只要你认真学&#xff0c;每天花1-2个小时空闲时间动动手指&#xff0c;日赚300-1000问题不大&#xff01; 搬砖是从国外steam市场置办游戏装备回来&#xff0c;在…

javassm运列车物资进销存及领用管理系统

主要对个人中心、生产部管理、财务部管理、库房部管理、用户管理、车型分类管理、线路信息管理、列车信息管理、物资分类管理、物资信息管理、储备定额管理、物资入库管理、物资申请管理、入库记录管理的实现。 本系统设计的现状和趋势&#xff0c;从需求、结构、数据库等方面的…

五、Git本地仓库基本操作——分支管理

1. 什么是分支&#xff1f; master分支 我们在初始化git仓库的时候&#xff0c;会默认创建一个master分支&#xff0c;HEAD指针这时就会默认执行master分支。当我们在master分支提交&#xff08;commit&#xff09;了更新之后&#xff0c;master分支就会指向当前当前最新的co…

微搭中如何实现弹性布局

我们在实际开发中经常可能会有一些社交的场景&#xff0c;比如开发一个类似朋友圈九宫格图片展示的功能。因为图片的数量不确定&#xff0c;所以需要实现图片的从左到右顺序排列。 在微搭中可以以可视化的方式设置样式。但是对于我们这类特殊需求&#xff0c;只用可视化设置显…

【SSL/TLS】准备工作:HTTPS服务器部署:Nginx部署

HTTPS服务器部署&#xff1a;Nginx部署1. 准备工作2. Nginx服务器YUM部署2.1 直接安装2.2 验证3. Nginx服务器源码部署3.1 下载源码包3.2 部署过程4. Nginx基本操作4.1 nginx常用命令行4.2 nginx重要目录1. 准备工作 1. Linux版本 [rootlocalhost ~]# cat /proc/version Li…

【宝塔部署PHP项目】含域名访问部署、IP访问部署、数据库、端口号、Nginx等知识

一定要弄懂项目部署的方方面面。当服务器上部署的项目过多时&#xff0c;端口号什么时候该放行、什么时候才会发生冲突&#xff1f;多个项目使用redis怎么防止覆盖&#xff1f;Nginx的配置会不会产生站点冲突&#xff1f;二级域名如何合理配置&#xff1f;空闲的时候要自己用服…

Day886.MySQL的“饮鸩止渴”提高性能的方法 -MySQL实战

MySQL的“饮鸩止渴”提高性能的方法 HI&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于MySQL的“饮鸩止渴”提高性能的方法的内容。 不知道在实际运维过程中有没有碰到这样的情景&#xff1a; 业务高峰期&#xff0c;生产环境的 MySQL 压力太大&#xff0c;没法正常响…

力扣SQL刷题8

目录1212. 查询球队积分1270. 向公司CEO汇报工作的所有人1285. 找到连续区间的开始和结束数字1321. 餐馆营业额变化增长--重要窗口函数知识点补充1212. 查询球队积分 题型&#xff1a;读题 解答&#xff1a;先考虑做主方时&#xff0c;再考虑客方时 SELECT t.team_id, t.te…

人工智能轨道交通行业周刊-第33期(2023.2.6-2.12)

本期关键词&#xff1a;高铁激光清洗、高铁确认列车、无线通信系统、推理服务优化、量子信息技术 1 整理涉及公众号名单 1.1 行业类 RT轨道交通中关村轨道交通产业服务平台人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟V…

大数据系列之:安装pulsar详细步骤

大数据系列之&#xff1a;安装pulsar详细步骤一、Pulsar版本和jdk对应关系二、安装JDK三、设置和激活jdk环境变量四、下载和解压Pulsar五、查看Pulsar目录六、启动Pulsar standalone cluster七、创建Kafka Topic八、往Topic写入数据九、消费pulsar的Topic一、Pulsar版本和jdk对…

c#小笔记本-基础

c#基本知识一.基础操作1.打印-writeline,write2.输入-readline,readkey二.变量1.折叠代码-#region&#xff0c;#endregion2.变量类型&#xff08;在c语言变量类型上新增的&#xff09;三.常量-const四.转义字符五.显示转换1.括号强转-低精度装高精度2.parse法-作用于字符串3.co…

实践指南|如何在 Jina 中使用 OpenTelemetry 进行应用程序的监控和跟踪

随着软件和云技术的普及&#xff0c;越来越多的企业开始采用微服务架构、容器化、多云部署和持续部署模式&#xff0c;这增加了因系统失败而给运维/ SRE / DevOps 团队带来的压力&#xff0c;从而增加了开发团队和他们之间的摩擦&#xff0c;因为开发团队总是想尽快部署新功能&…

28岁才转行软件测试,目前32了,我的一些经历跟感受

我是92年的&#xff0c;算是最早的90后&#xff0c;现在跟你介绍的时候还恬不知耻的说我是90后&#xff0c;哈哈&#xff0c;计算机专业普通本科毕业。在一个二线城市&#xff0c;毕业后因为自身能力问题、认知水平问题&#xff0c;再加上运气不好&#xff0c;换过多份工作&…

关于@hide的理解

在上一篇文章《学习HandlerThread》我们提到虽然HandlerThread类里有getThreadHandler()方法得到Handler&#xff0c;但是我们不可能调用到它。因为这个方法用hide注释了 /*** return a shared {link Handler} associated with this thread* hide*/NonNullpublic Handler getT…

数据一致性

目录一、AOP 动态代理切入方法(1) Aspect Oriented Programming(2) 切入点表达式二、SpringBoot 项目扫描类(1) ResourceLoader 扫描类(2) Map 的 computeIfAbsent 方法(3) 反射几个常用 api① 创建一个测试注解② 创建测试 PO 类③ 反射 api 获取指定类的指定注解信息(4) 返回…

基于Golang哈希算法监控配置文件变化

SHA(secure hashing algorithm)表示安全哈希算法.SHA是MD5的修正版本&#xff0c;用于数据摘要和认证。哈希和加密类似&#xff0c;唯一区别是哈希是单项的&#xff0c;即哈希后的数据无法解密。SHA有不同的算法&#xff0c;主要包括SHA-1, SHA-2, SHA-256, SHA-512, SHA-224, …

1.2.6存储结构-磁盘管理:单缓冲区与双缓冲区读取、流水线周期、计算流水线执行时间

1.2.6存储结构-磁盘管理&#xff1a;单缓冲区与双缓冲区读取、流水线周期、计算流水线执行时间流水线周期计算流水线执行时间微秒&#xff0c;时间单位&#xff0c;符号μs&#xff08;英语&#xff1a;microsecond &#xff09;&#xff0c;1微秒等于百万分之一秒&#xff08;…