【Android 13源码分析】Activity生命周期之onCreate,onStart,onResume-2

news2024/11/20 20:44:40

忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。
                  
                  
                                           – 服装学院的IT男

本篇已收录于Activity短暂的一生系列
欢迎一起学习讨论Android应用开发或者WMS
V:WJB6995
Q:707409815

正文

在这里插入图片描述

生命周期系列:

  • Activity生命周期之onPause

  • onCreate,onStart,onResume-1

  • onCreate,onStart,onResume-2

  • Activity生命周期之onStop-1

  • Activity生命周期之onStop-2

  • Activity生命周期之onDestory

本篇为"onCreate,onStart,onResume"的第二篇,介绍应用端 onCreate,onStart,onResume 的处理

1. onCreate

onCreate 是一个新 Activity 启动的第一个生命周期。而且根据前面的铺垫,也知道了他是在 onStart 和 onResume 执行的。
对应的事务为 LaunchActivityItem

# LaunchActivityItem
    @Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
            // trace
            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
            ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                    mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                    mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
                    client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
                    mTaskFragmentToken);
            // 应用段处理
            client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
    @Override
    public void postExecute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        
            client.countLaunchingActivities(-1);
    }

完整的调用链如下:

LaunchActivityItem::execute
    ActivityThread::handleLaunchActivity
        ActivityThread::performLaunchActivity
            Instrumentation::newActivity      --- 创建Activity
            Activity::attach                  --- 创建Window
                Window::init
                Window::setWindowManager
            Instrumentation::callActivityOnCreate  
                Activity::performCreate
                    Activity::onCreate        --- onCreate
            ActivityClientRecord::setState    --- 设置状态为 ON_CREATE(1)

这部分的代码其实在【Activity启动流程-3】的末尾有解释,单独拎出来再看一遍。

# ActivityThread

    public Activity handleLaunchActivity(ActivityClientRecord r,
                PendingTransactionActions pendingActions, Intent customIntent) {
                    ......
                    final Activity a = performLaunchActivity(r, customIntent);
                    ......
                }
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ......
                Activity activity = null;
                try {
                    // 重点* 1. 通过Instrumentation 反射创建Activity
                    java.lang.ClassLoader cl = appContext.getClassLoader();
                    activity = mInstrumentation.newActivity(
                            cl, component.getClassName(), r.intent);
                    ......
                }
                try {
                    ......
                    // 重点* 2. 执行 attach 流程
                    activity.attach(appContext, this, getInstrumentation(), r.token,
                            r.ident, app, r.intent, r.activityInfo, title, r.parent,
                            r.embeddedID, r.lastNonConfigurationInstances, config,
                            r.referrer, r.voiceInteractor, window, r.activityConfigCallback,
                            r.assistToken, r.shareableActivityToken);
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                    } else {
                        重点* 3. OnCreate流程
                        mInstrumentation.callActivityOnCreate(activity, r.state);
                    }
                    // 设置状态为 ON_CREATE(1)
                    r.setState(ON_CREATE);
                } ......
        ......
    }

# Instrumentation
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        // onCreate流程
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }
# Activity
    final void performCreate(Bundle icicle) {
        performCreate(icicle, null);
    }
    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        ......
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            // 执行onCreate
            onCreate(icicle);
        }
        // wm_on_create_called
        EventLogTags.writeWmOnCreateCalled(mIdent, getComponentName().getClassName(),
                "performCreate");
        ......
    }

onCreate 的流程还是比较简单的,在 ActivityThread::performLaunchActivity 做了四件事:

    1. 反射创建 Activity 对象
    1. 执行 activity.attach,这里会创建Window
    1. 执行到 onCreate 生命周期
    1. 设置 ActivityClientRecord 中的状态为 ON_CREATE(1)

这里需要留意下会先执行 Activity::attach 来创建Window,然后才是后面的 Activity的onCreate。
创建 Window 的时候会创建 DecorView,有了这个 DecorView 我们在 onCreate 的时候才可以把对应的XML布局设置进去。

2. onStart

onStart 也有其对应的一个事务: StartActivityItem ,我一度以为启动 Activity 的时候也是通过这个事务来触发 onStart 的,但是实际情况我有点意外,它不是通过事务触发的,而是在执行 ResumeActivityItem 前,通过 TransactionExecutor::cycleToPath 触发的。

按下 recent 键再回到 Activity,这个时候onStart 是通过 StartActivityItem 触发的

当前分析 TransactionExecutor::cycleToPath 方法

# TransactionExecutor
    // 工具类
    private TransactionExecutorHelper mHelper = new TransactionExecutorHelper();    

    private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
            ClientTransaction transaction) {
        // 1. 获取当前ActivityClientRecord的生命周期状态值
        final int start = r.getLifecycleState();
        // log 
        if (DEBUG_RESOLVER) {
            Slog.d(TAG, tId(transaction) + "Cycle activity: "
                    + getShortActivityName(r.token, mTransactionHandler)
                    + " from: " + getStateName(start) + " to: " + getStateName(finish)
                    + " excludeLastState: " + excludeLastState);
        }
        // 2. 根据起始状态、结束状态以及是否排除最后一个状态,计算出生命周期状态变化的路径
        final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
        // 3. 按照计算出的生命周期状态路径顺序执行相关操作
        performLifecycleSequence(r, path, transaction);
    }
    1. 获取到当前 Activity 的生命周期状态,目前是 ON_CREATE 也就是 1
    1. 通过工具类 计算出生命周期变化的路径,这个路径是啥呢, 比如说当前是 ON_CREATE(1),需要到 ON_RESUME(3), 那路径就是 [2]
    1. 根据第二步计算的路径开始执行各个生命周期

2.1 getLifecyclePath 计算生命周期切换路径

TransactionExecutor::getLifecyclePath 方法完整代码和解释都在下面了,但是我个人建议了解一下即可,大概浏览一下,留意我代码加了1,2,3 这3个重点的地方即可。

# TransactionExecutorHelper
    // 定义需要经过的生命周期路径,长度为6(毕竟一共也才7个生命周期)
    @ActivityLifecycleItem.LifecycleState
    private IntArray mLifecycleSequence = new IntArray(6);

    // start   :开始的生命周期状态
    // finish  :结束的生命周期状态
    // excludeLastState :是否移除最后一个状态
    public IntArray getLifecyclePath(int start, int finish, boolean excludeLastState) {

        // 如果开始状态或结束状态未定义,则抛出异常
        if (start == UNDEFINED || finish == UNDEFINED) {
            throw new IllegalArgumentException("Can't resolve lifecycle path for undefined state");
        }

        // 如果开始状态或结束状态是ON_RESTART,则抛出异常,因为在生命周期中不能以此状态开始或结束
        if (start == ON_RESTART || finish == ON_RESTART) {
            throw new IllegalArgumentException(
                    "Can't start or finish in intermittent RESTART state");
        }

        // 如果结束状态为PRE_ON_CREATE且开始状态不等于结束状态,则抛出异常,只能从预创建状态开始
        if (finish == PRE_ON_CREATE && start != finish) {
            throw new IllegalArgumentException("Can only start in pre-onCreate state");
        }

        // 重点* 1. 清空用于存储生命周期状态变更序列的集合
        mLifecycleSequence.clear();

        // 重点* 2. 分情况计算生命周期状态变更路径 (正常场景)
        if (finish >= start) {
            // 如果结束状态大于等于开始状态
            if (start == ON_START && finish == ON_STOP) {
                // 特殊情况:从开始到停止状态,无需经过暂停和恢复状态
                mLifecycleSequence.add(ON_STOP);
            } else {
                // 重点* 3. 普通情况:直接将中间的所有状态加入序列 (正常场景)
                for (int i = start + 1; i <= finish; i++) {
                    mLifecycleSequence.add(i);
                }
            }
        } else { // 结束状态小于开始状态,不能简单地向下循环
            if (start == ON_PAUSE && finish == ON_RESUME) {
                // 特殊情况:从暂停直接到恢复状态
                mLifecycleSequence.add(ON_RESUME);
            } else if (start <= ON_STOP && finish >= ON_START) {
                // 开始状态在ON_STOP之前且结束状态在ON_START之后的情况
                // 先转为停止状态
                for (int i = start + 1; i <= ON_STOP; i++) {
                    // 添加
                    mLifecycleSequence.add(i);
                }
                // 添加
                mLifecycleSequence.add(ON_RESTART);
                // 再转到指定结束状态
                for (int i = ON_START; i <= finish; i++) {
                    mLifecycleSequence.add(i);
                }
            } else {
                // 其他情况:需要重新启动并转到指定状态
                // 先转到销毁状态
                for (int i = start + 1; i <= ON_DESTROY; i++) {
                    // 添加
                    mLifecycleSequence.add(i);
                }
                // 再转到指定结束状态
                for (int i = ON_CREATE; i <= finish; i++) {
                    // 添加
                    mLifecycleSequence.add(i);
                }
            }
        }

        // 如果要求排除最后一个状态并且生命周期序列不为空,则移除最后一个状态
        if (excludeLastState && mLifecycleSequence.size() != 0) {
            mLifecycleSequence.remove(mLifecycleSequence.size() - 1);
        }

        // 返回计算好的生命周期状态变更序列
        return mLifecycleSequence;
    }

根据当前分析的场景,这个方法执行以下3步:

    1. 清除集合的数据,避免有脏数据影响结果
    1. 当前第一个参数是 ON_CREATE(1), 第二个参数定义在 ResumeActivityItem 下,返回值是 ON_RESUME(3),满足finish >= start的条件,所以进if语句
    1. 走 else 逻辑,最终 mLifecycleSequence 下也就一个元素 : 2 ,返回返回

2.2 performLifecycleSequence 切换Activity的生命周期

上一小节计算出需要执行的生命周期路径后,现在就要开始应用了。

# TransactionExecutor
    // 实际执行在 ActiviThread
    private ClientTransactionHandler mTransactionHandler;
    // 构造方法赋值
    public TransactionExecutor(ClientTransactionHandler clientTransactionHandler) {
        mTransactionHandler = clientTransactionHandler;
    }

    private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
            ClientTransaction transaction) {
            // 当前场景就1个元素
            final int size = path.size();
            // 开始遍历
            for (int i = 0, state; i < size; i++) {
                // 获取到状态,当前就1个元素:ON_START( 2)
                state = path.get(i);
                // 打印log
                if (DEBUG_RESOLVER) {
                    Slog.d(TAG, tId(transaction) + "Transitioning activity: "
                            + getShortActivityName(r.token, mTransactionHandler)
                            + " to state: " + getStateName(state));
                }
                switch (state) {
                    ......
                    case ON_START:
                        mTransactionHandler.handleStartActivity(r, mPendingActions,
                                null /* activityOptions */);
                        break;
                    ......
                }         
            }
        }

mTransactionHandler 在构造 TransactionExecutor 的构造方法赋值,创建对象的地方在 ActivityThread 中,传递的参数是 this,而 ActivityThread 是 ClientTransactionHandler 的子类,也就是说 mTransactionHandler 真正的实现还是在 ActivityThread。

# ActivityThread
    @Override
    public void handleStartActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, ActivityOptions activityOptions) {
            // 拿到 Activity
            final Activity activity = r.activity;
            ......
            // Start
            // 重点* 1. 执行onStart
            activity.performStart("handleStartActivity");
            // 2. 更新对应的状态
            r.setState(ON_START);
            ......
            // 重点* 3. 更新可见性,参数为true
            updateVisibility(r, true /* show */);
            mSomeActivitiesChanged = true;
            ......
        }

一共处理了3件事,其中设置状态的逻辑之前看过了,看看另外2个重点流程。

2.3 onStart 流程

# Activity
    final void performStart(String reason) {
        ......
        // 执行onStart
        mInstrumentation.callActivityOnStart(this);
        // wm_on_start_called
        EventLogTags.writeWmOnStartCalled(mIdent, getComponentName().getClassName(), reason);
        ......
        // Fragment 处理
        mFragments.dispatchStart();
        ......
    }

# Instrumentation

    public void callActivityOnStart(Activity activity) {
        activity.onStart();
    }

到这里 Activity 的 onStart 就执行了。

2.4 设置 View 可见

上一小节先执行到 onStart ,然后会设置 View 的可见性, 看一下具体代码

# ActivityThread
    private void updateVisibility(ActivityClientRecord r, boolean show) {
        // 拿到DecorView
        View v = r.activity.mDecor;
        if (v != null) {
            if (show) {
                if (!r.activity.mVisibleFromServer) {
                    r.activity.mVisibleFromServer = true;
                    mNumVisibleActivities++;
                    if (r.activity.mVisibleFromClient) {
                        // 设置 View 可见 (当前逻辑)
                        r.activity.makeVisible();
                    }
                }
            } else {
                if (r.activity.mVisibleFromServer) {
                    r.activity.mVisibleFromServer = false;
                    mNumVisibleActivities--;
                    // 隐藏View
                    v.setVisibility(View.INVISIBLE);
                }
            }
        }
    }

当前是 onStart 逻辑,也看到了方法传递的参数是 true,说明要设置可见,所以会执行 Activity::makeVisible 逻辑。

# Activity

    void makeVisible() {
        if (!mWindowAdded) { // 之前setView时已置位true
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        // 设置可见
        mDecor.setVisibility(View.VISIBLE);
    }

2.5 onStart 小结

启动一个Activity 执行到 onStart 流程的分析就结束了,完整调用链如下:

TransactionExecutor::cycleToPath
    TransactionExecutorHelper::getLifecyclePath
    TransactionExecutor::performLifecycleSequence
        ClientTransactionHandler::handleStartActivity
            ActivityThread::handleStartActivity
                Activity::performStart           -- onStart
                    Instrumentation::callActivityOnStart
                        Activity::onStart
                ActivityClientRecord::setState   -- 状态设置为 ON_START
                ActivityThread::updateVisibility -- 更新View可见性
                    Activity::makeVisible
                        View::setVisibility      -- VISIBLE

如果是按多任务键(Recent)再回到 Activity 是会执行 ActivityRecord::makeActiveIfNeeded 来构建 StartActivityItem 事务处理 onStart 流程,但是后续的逻辑还是一样的

我们知道 onStart 和 onStop 是成对的, 那 onStart 会执行 View::setVisibility 设置 View 可见,那相对的在 onStop 流程是不是就会 设置 View 不可见呢?

这个疑问留到下一篇 onStop 流程解答。

当前还是继续看 onResume 的执行

3. onResume

onResume 对应事务为 ResumeActivityItem

# ResumeActivityItem

    @Override
    public void execute(ClientTransactionHandler client, ActivityClientRecord r,
            PendingTransactionActions pendingActions) {
            // Trace
            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
            // 应用端处理
            client.handleResumeActivity(r, true /* finalStateRequest */, mIsForward,
                    "RESUME_ACTIVITY");
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

    @Override
    public void postExecute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        // TODO(lifecycler): Use interface callback instead of actual implementation.
        ActivityClient.getInstance().activityResumed(token, client.isHandleSplashScreenExit(token));
    }

    @Override
    public int getTargetState() {
        return ON_RESUME;
    }

调用链如下:

ResumeActivityItem::execute
    ActivityThread::handleResumeActivity
        ActivityThread::performResumeActivity   
            Activity::performResume     
                Instrumentation::callActivityOnResume
                    Activity::onResume           -- onResume
                ActivityClientRecord::setState   -- ON_RESUME
        WindowManagerImpl::addView               -- 创建ViewRootImpl
            WindowManagerGlobal::addView   
                ViewRootImpl::setView            -- 与WMS通信与WMS通信触发窗口的显示逻辑

开始撸代码。

# ActivityThread
    public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
            boolean isForward, String reason) {
        ......
        // 触发onResume
        if (!performResumeActivity(r, finalStateRequest, reason)) {
            return;
        }
        ......
        // 拿到activity
        final Activity a = r.activity;
        ......
        if (r.window == null && !a.mFinished && willBeVisible) {
            // 将本地的window设置到activityRecord中
            r.window = r.activity.getWindow();
            // 获取DecorView
            View decor = r.window.getDecorView();
            // 设置不可见  在后面调用Activity::makeVisible会设为可见
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager();
            // 获取参数
            WindowManager.LayoutParams l = r.window.getAttributes();
            // DecorView设置给Activity
            a.mDecor = decor;
            // 设置Activity的windowType,注意这个type,才是应用的窗口类型
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            ......
            if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    // 重点:执行addView,并设置mWindowAdded=true
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                } else {
                    a.onWindowAttributesChanged(l);
                }
            }

        } else if (!willBeVisible) {
            if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
            r.hideForNow = true;
        }
        ......
        r.nextIdle = mNewActivities;
        mNewActivities = r;
        // stop 逻辑的触发
        if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
        Looper.myQueue().addIdleHandler(new Idler());
    }

当前分析 onResume 生命周期,所以只看 performResumeActivity 方法就好。

# ActivityThread

    @VisibleForTesting
    public boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
            String reason) {
            // log
            if (localLOGV) {
                Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished);
            }
                ......
                // 触发 onResume
                r.activity.performResume(r.startsNotResumed, reason);
                // 设置状态
                r.setState(ON_RESUME);
                ......
        }
# Activity
    final void performResume(boolean followedByPause, String reason) {
            // trace
            if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performResume:"
                        + mComponent.getClassName());
            }
            ......
            // 主流程
            mInstrumentation.callActivityOnResume(this);
            // wm_on_resume_called
            EventLogTags.writeWmOnResumeCalled(mIdent, getComponentName().getClassName(), reason);
            ......
            // Fragments 处理
            mFragments.dispatchResume();
            ......
    }

流程和其他的一样,也是先通过 Instrumentation 然后又回到 Activity 处理,然后打印另一个 events 日志。

# Instrumentation
    public void callActivityOnResume(Activity activity) {
        activity.mResumed = true;
        activity.onResume();
    }

4. 总结

SourceActivity 在启动过程中会执行的3个生命周期已经分析完了,当前分析的场景下有以下几个点:

    1. 这3个生命周期的执行的连续的,
    1. onStart 原来这个场景下不是通过事务执行的
    1. 知道了 Activity 生命周期事务跨进程处理方式
    1. DecorView 的可见性是在 onStart 设置的
    1. 执行 onResume 的时候会触发窗口的添加显示,从严格意义上说,执行 onResume 的时候并不意味着手机屏幕上就有UI数据了。(但是不那么严谨思考的话,正常情况下,onResume 执行了差不多窗口也就显示了)

关于 events 日志的整理如下:

    1. wm_restart_activity 的触发在 ActivityTaskSupervisor::realStartActivityLocked 方法构建2个事务的时候,表示 SystemService 端要真正触发 TargetActivity 启动
    1. wm_on_create_called 的触发在 Activity::performCreate 方法,表示TargetActivity端执行 onCreate
    1. wm_on_start_called 的触发在 Activity::performStart 方法,表示TargetActivity端执行 onStart
    1. wm_on_resume_called 的触发在 Activity::performResume 方法,表示TargetActivity端执行 onResume

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

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

相关文章

无源码实现免登录功能

因项目要求需要对一个没有源代码的老旧系统实现免登录功能&#xff0c;系统采用前后端分离的方式部署&#xff0c;登录时前端调用后台的认证接口&#xff0c;认证接口返回token信息&#xff0c;然后将token以json的方式存储到cookie中&#xff0c;格式如下&#xff1a; 这里有…

10月1日星期二今日早报简报微语报早读

10月1日星期二&#xff0c;国庆节&#x1f1e8;&#x1f1f3;&#xff0c;农历八月廿九&#xff0c;早报#微语早读。 1、A股暴涨刷新多项历史纪录&#xff1a;两市成交总额近2.6万亿元&#xff0c;创指涨逾15%&#xff1b; 2、文旅部&#xff1a;常年不超过最高承载量的旅游景…

Docker 安装 Citus 单节点集群:全面指南与详细操作

Docker 安装 Citus 单节点集群&#xff1a;全面指南与详细操作 文章目录 Docker 安装 Citus 单节点集群&#xff1a;全面指南与详细操作一 服务器资源二 部署图三 安装部署1 创建网络2 运行脚本1&#xff09;docker-compose.cituscd1.yml2&#xff09;docker-compose.cituswk1.…

zi2zi-chain: 中国书法字体图片生成和字体制作的一站式开发

在zi2zi-pytorch的基础上&#xff0c;做了进一步的修复和完善。本项目github对应网址为https://github.com/not-bald-owl/zi2zi-chain/tree/master。 修复部分为&#xff1a;针对预处理部分的函数弃用、生僻字无法生成、训练和推理部分单卡支持改为多卡并行、以及扩展从本地的…

过去8年,编程语言的流行度发生了哪些变化?PHP下降,Objective-C已过时

前天有一个汇总9个不同排名数据的“地表最强”编程语言排行榜&#xff0c;为了更好地理解语言流行度的变化&#xff0c;作者将2016年的类似调查结果与2024年的数据进行了比较。 虽然2016年的调查只包含6个排名&#xff0c;但它仍然提供了宝贵的参考数据。 我们来看看详细的情…

C++之String类(下)

片头 嗨喽~ 我们又见面啦&#xff0c;在上一篇C之String类&#xff08;上&#xff09;中&#xff0c;我们对string类的函数有了一个初步的认识&#xff0c;这一篇中&#xff0c;我们将继续学习string类的相关知识。准备好了吗&#xff1f;咱们开始咯~ 二、标准库中的string类 …

业务封装与映射 -- AMP BMP GMP

概述 不同单板支持不同的封装模式&#xff0c;主要包括: AMP (Asynchronous Mapping Procedure&#xff0c;异步映射规程)BMP (Bit-synchronous Mapping Procedure&#xff0c;比特同步映射规程)GMP (Generic Mapping Procedure&#xff0c;通用映射规程) AMP/BMP&#xff1a…

Qt_绘图

目录 1、绘图核心类 2、QPainter类的使用 2.1 绘制线段 2.2 绘制矩形 2.3 绘制圆形 2.4 绘制文本 3、QPen类的使用 3.1 使用画笔 4、QBrush类的使用 4.1 使用画刷 5、绘制图片 5.1 测试QPixmap 5.1.1 图片移动 5.1.2 图标缩小 5.1.3 旋转图片 5.1.4 将…

【逐行注释】MATLAB下的粒子滤波代码(三维状态与观测,可直接复制粘贴到MATLAB上面运行)

文章目录 程序设计1. 介绍2. 系统模型3. 算法步骤源代码(直接复制到MATLAB上面可以运行)运行结果程序设计 1. 介绍 粒子滤波(Particle Filter, PF)是一种基于贝叶斯理论的递归估计方法,广泛用于动态系统状态的估计和跟踪。该方法通过一组粒子(即假设的状态)及其权重来…

【Android 13源码分析】Activity生命周期之onCreate,onStart,onResume-1

忽然有一天&#xff0c;我想要做一件事&#xff1a;去代码中去验证那些曾经被“灌输”的理论。                                                                                  – 服装…

5款惊艳全网的AI写作论文神器!从此告别写作烦恼!

在当今的学术研究和写作领域&#xff0c;撰写高质量的论文是一项挑战性的任务。幸运的是&#xff0c;随着人工智能技术的发展&#xff0c;AI论文写作工具逐渐成为帮助学者和学生提高写作效率的重要工具。这些工具不仅能够提高写作效率&#xff0c;还能帮助研究者生成高质量的论…

ECharts 快速使用

最终效果 使用介绍 echarts图表的绘制&#xff0c;大体分为三步&#xff1a; 根据 DOM实例&#xff0c;通过 echarts.init方法&#xff0c;生成 echarts实例构建 options配置对象&#xff0c;整个echarts的样式&#xff0c;皆有该对象决定最后通过实例.setOption方法&#xf…

【测试-BUG篇】软件测试的BUG知识你了解多少呢?

文章目录 1. 软件测试的生命周期2. BUG3. BUG的生命周期4. 与开发人员起争执怎么办 1. 软件测试的生命周期 &#x1f34e;软件测试 贯穿整个软件的生命周期&#xff1b; &#x1f34e;软件测试的生命周期是指测试流程&#xff1b; ①需求分析 用户角度&#xff1a;软件需求是…

C++:一文搞懂友元类(friend class)

C的友元&#xff08;friend&#xff09;是个很重要的概念&#xff0c;好些朋友对此却很迷惑&#xff0c;本文将对友元类&#xff08;friend class&#xff09;详细讲解&#xff0c;一文搞懂。 友元的特性&#xff1a; 1、使用friend修饰的友元类可以访问本类的私有成员(priva…

中国电信解锁万亿参数大模型:TeleAI的创新与突破

首个由万卡集群训练出来的万亿参数大模型&#xff0c;已被一家央企解锁。 具体而言&#xff0c;为了推动纯国产人工智能的探索&#xff0c;带来这条新路径的正是中国电信人工智能研究院&#xff08;TeleAI&#xff09;。 该研究院由中国电信集团的CTO、首席科学家兼院长李学龙…

坡印廷矢量(也叫功率流密度,对面积积分就是功率)

坡印廷矢量在静电场&#xff0c;静磁场&#xff0c;恒定电流的电场&#xff0c;和时变电磁场中的表达式不同。 我们看时变电磁场的坡印廷矢量 坡印廷矢量就等于这个&#xff0c;其中的电场和磁场是实数表示的 坡印廷矢量用复数形式的场求 这里的E和H是复数表示的场&#xff0…

电影票接口api对接有哪些优势?

一、业务功能拓展方面的优势 多平台整合可以整合多个影院票务系统&#xff0c;通过一个接口获取众多影院的信息&#xff0c;包括影院、影厅、座位、影片、场次、日期及票价等信息&#xff0c;方便在自己的应用程序中展示这些信息&#xff0c;从而实现电影票的在线预订、支付和…

人工智能价格战——如何降低成本让人工智能更易于普及

十年前&#xff0c;开发人工智能 (AI) 是只有大公司和资金充足的研究机构才能负担得起的事情。必要的硬件、软件和数据存储成本非常高。但从那时起&#xff0c;情况发生了很大变化。一切始于 2012 年的 AlexNet&#xff0c;这是一种深度学习模型&#xff0c;展示了神经网络的真…

微服务jvisualvm解析部署使用全流程

1、介绍 VisualVM 是Netbeans的profile 2、启动 进入正在使用的jdk下bin目录&#xff0c;运行jvisualvm.exe。 3、选中要监控的线程 4、安装gc插件 5、插件安装报错 VisualVM: Plugins Centers 访问这个地址&#xff0c;找到对应版本再配置 https://visualvm.github.io/uc/…

【CKA】六、四层负载-Service应用

6、四层负载-Service应用 1. 考题内容&#xff1a; 2. 答题思路&#xff1a; 1、编辑front-end的deploy服务&#xff0c;添加端口信息 2、暴露svc端口 3. 官网地址&#xff1a; https://kubernetes.io/zh-cn/docs/tutorials/services/connect-applications-service/#the-ku…