Android复习(Android基础-四大组件)—— Activity

news2024/11/16 1:34:34
  • Activity作为四大组件之首,是使用最为频繁的一种组件,中文直接翻译为"活动",不过如果被翻译为"界面"会更好理解。正常情况,除了Window,Dialog和Toast , 我们能见到的界面只有Activity。

1. 进程模式

  • APP进程的级别,由其活跃的处于栈顶的组件的活动状态(比如生命周期)决定。
  • Activity的进程模式分为:前台进程、可见进程、Service进程、后台进程、空白进程
  1. 前台进程适用于目前操作所需的进程。在不同的情况下,进程可能因为其所包含的各种应用组件而被视为前台进程。以下任一条件成立,就是前台进程。
  • 当前进程Activity正在与用户进行交互。(已调用onResume)
  • 当前Service正在执行回调的代码 生命周期(Service.onCreate() , Service.onStart(), Service.onDestory())
  • 进程有一个正在运行的BroadcastReceiver(BroadcastReceiver.onReceive()正在执行)
  1. 可见进程:前台进程是一个Dialog;进程有一个Service,这个Service正在和一个可见的Activity绑定。
  • Activity在屏幕上对用户可见,但是失去了焦点,调用了onPause,暂时无法操作。
  • Service正在通过Service.startForeground()。
  • 实现特定功能的系统服务:动态壁纸,输入法服务。
  1. 服务进程:服务进程包含了一个已使用startService()方法启动的Service的进程。

  2. 后台进程:当Activity的onStop被调用,但是onDestroy并没有被调用

  3. 空白进程:当系统需要内存的时候,会暂时将背景进程清除,就成为了空白进程。

  • 进程优先级:前台进程 > 可见进程 > service进程 > 后台进程 > 空进程
  • 系统内存不足时,会删除优先级低的进程。

2. Activity的生命周期

  1. onCreate:表示Activity正在被创建,这是生命周期的第一个方法。可以做一些初始化的工作(加载界面布局资源,初始化Activity所需数据)
  2. onRestart:表示Activity正在被重新启动。一般情况下,当当前Activity从不可见更新为可见状态的时候,onRestart就会被调用
  3. onStart:表示Activity正在被启动,即将开始。这时Activity已经可见,但是没有出现在前台,还无法和用户交互了。
  4. onResume:表示Activity已经可见,并且出现在前台并开始活动。要注意这个和onStart的对比。onStart和onResume都表示Activity已经可见,但是onStart的时候Activity还在后台,onResume的时候Activity才显示到前台。
  5. onPause:表示Activity正在暂停,正常情况下,紧跟着onStop就会被调用。在特殊情况下,如果快速再回到当前Activity,那么onResume会被调用。(这种属于特殊情况,一般不会发生)。在这可以做一些存储数据,停止动画等操作,但是注意不能太耗时,不然会影响到新Activity的显示,onPause执行完,新的Activity的onResume才会执行。
  6. onStop:表示Activity即将停止,可以做一些稍微重量级的回收工作,同样不能太过耗时。
  7. onDestroy:表示Activity即将被销毁,这是生命周期中的最后一个回调。在这里,我们可以做一些回收工作和最终资源的释放。
    在这里插入图片描述

2.1 典型情况下的生命周期

  1. 打开新的Activity或者切换到桌面的时候,生命周期的回调?
    在这里插入图片描述
  2. onStart 和 onResume、onPause 和 onStop实质有什么不同?
    在这里插入图片描述
  3. 假设当前Activity为A,如果这时用户打开了一个新的ActivityB,那么B的onResume和A的onPause哪个先执行呢?
    在这里插入图片描述

2.2 异常情况下的生命周期

  • Activity除了受用户操作所导致的正常的生命周期方法调度,还有一些异常情况,比如当资源相关的系统配置发生改变以及系统内存不足时,Activity可能会被杀死。

2.2.1 情况1:资源相关的系统配置发生改变导致Activity被杀死并重新创建

  1. 首先要对系统的资源加载机制有一定的理解。把一张图片放在drawable目录后,可以通过Resources去获取这张图片。同时为了兼容不同的设备,我们可能还需要在其他一些目录放置不同的图片,比如drawable-mdpi、drawable-hdpi 等等。 这样,当应用程序启动的时候,系统就会根据设备去加载合适的Resources资源。比如说横屏手机和竖屏手机会**拿到两张不同的图片。
  2. 突然旋转屏幕,由于**系统配置发生了变化,在默认情况下,Activity就会被销毁并且重新创建,当然我们也可以组织重新创建我们的Activity
    在这里插入图片描述

2.2.2 情况2:资源内存不足导致优先级低的Activity被杀死

  • 这种情况不好模拟,但是其数据存储和恢复过程和情况1完全一致。这里我们简单描述一下Activity的优先级情况。
  • 前台进程 > 可见进程 > 服务进程 > 后台进程 > 空进程
  1. 前台Activity——正在和用户进行交互的Activity,优先级最高
  2. 可见但非前台Activity——比如Activity弹出了一个对话框,导致Activity可见,但是位于后台无法和用户直接交互。
  3. 后台Activity——已被暂停的Activity,比如执行了onStop,优先级最低。

如果一个进程中没有四大组件在执行,那么这个进程很快就会被系统杀死。因此,一些后台工作不适合脱离四大组件而独自运行在后台中,这样进程很容易被杀死。比较好的方法是将后台工作放入Service中从而保证有一定的优先级,这样就不会轻易被杀死。

3. Activity的重建机制

  • 重建机制就是在onStop()后,调用onSaveInstanceState将Activity的某些状态保存下来。然后在重新创建onStart()之后调用onRestoreInstanceState()把这状态显示出来。
  1. onSaveInstanceState:这个方法将要保存的数据 以键值对形式 保存在Bundle对象中。并把保存下来的bundle对象作为参数同时传递给onRestoreInstanceState和onCreate,保存了当前Activity的视图结构。(API29之后一定会调用在onStop之后)
  2. onRestoreInstanceState:一旦被调用,Bundle参数一定有值,不用额外判空,但onCreate正常启动Bundle参数为null。

3.1 onSaveInstanceState & onRestoreInstanceState

  • 主要是 onSaveInstanceStateonRestoreInstanceState方法。
  • 系统为我们做了一定的恢复工作。当Activity在异常情况下需要重新创建时,系统会默认为我们保存当前Activity 的视图结构,并且在 Activity重启后为我们恢复这些数据。
  • 例如:文本框(TextView)中用户输入的数据、ListView滚动的位置等。这些View相关的状态系统都能够默认为我们恢复。
  • 针对某一特定的View系统能够为我们恢复哪些数据,我们可以查看View的源码。 和Activity一样,每个View都有onSaveInstanceStateonRestoreInstanceState。 看一下它们的具体实现,就可以知道系统自动为每个View恢复哪些数据。
  • 拿TextView来说,我们分析一下它保存了哪些数据。
@Override
public Parcelable onSaveInstanceState() {
    Parcelable superState = super.onSaveInstanceState();

    // Save state if we are forced to
    final boolean freezesText = getFreezesText();
    //文本框是否选中
    boolean hasSelection = false;
    int start = -1;
    int end = -1;
    //如果文本框不为空
    if (mText != null) {
        start = getSelectionStart();
        end = getSelectionEnd();
        if (start >= 0 || end >= 0) {
            // Or save state if there is a selection
            //表示选中
            hasSelection = true;
        }
    }

    if (freezesText || hasSelection) {
        SavedState ss = new SavedState(superState);

        if (freezesText) {
            if (mText instanceof Spanned) {
                final Spannable sp = new SpannableStringBuilder(mText);

                if (mEditor != null) {
                    removeMisspelledSpans(sp);
                    sp.removeSpan(mEditor.mSuggestionRangeSpan);
                }

                ss.text = sp;
            } else {
            //保存文本框上的数据
                ss.text = mText.toString();
            }
        }

        if (hasSelection) {
            // XXX Should also save the current scroll position!
            ss.selStart = start;
            ss.selEnd = end;
        }

        if (isFocused() && start >= 0 && end >= 0) {
            ss.frozenWithFocus = true;
        }

        ss.error = getError();

        if (mEditor != null) {
            ss.editorState = mEditor.saveInstanceState();
        }
        return ss;
    }

    return superState;
}

在这里插入图片描述

3.2 Activity的configChanges属性

  • 上面分析了系统的数据存储和恢复机制,我们知道,当系统配置发生改变的时候,Activity会被重新创建,有没有办法不重新创建呢?系统配置中有很多内容,如果当某项内容发生改变后,我们不想系统重新创建Activity。可以给Activity指定configChanges属性。
android:configChanges="orientation"
  • 如果我们想指定多个值,可以用 " |" 连接起来。
    在这里插入图片描述
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.activitytext" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ActivityText" >
        <activity
            android:name=".MainActivity"
            //我们常用的只有locale,orientation,keyboardHidden这三个选项
            android:configChanges="orientation|screenSize"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

3.3 重建机制中保存和恢复数据

保存数据

  • Activity通过onSaveInstanceState()方法来保存状态,onSaveInstanceState()执行在onStop()后。
  • 然后Activity会委托Window去保存数据,接着Window再委托它上面的等级容器去保存数据。
  • 顶层容器是一个ViewGroup,一般来说可能是一个DecorView
  • 最后顶层容器再去通知它的子元素来保存数据,这样整个保存数据过程就完成了。
    Activity里面有两个数据结构专门保存状态
  1. View States保存View的状态
  2. Instance State存储View states 以及开发者在 onSaveInstanceState中手动保存的Activity成员变量。

恢复数据

  • 通过onRestoreInstanceState方法来恢复状态,在保存期间,会自动收集View Hieracht(视图层次)中每一个实现了状态保存和恢复方法的View状态,这些数据会在onRestoreInstanceState方法时回传给View,并且回传是根据view的id来逐一匹配。

注意事项

  1. 为了成功保存状态,要求在View内部实现保存和恢复的算法。(原生的View都有做到,自定义View需要自己来重写实现)
  2. 为了成功恢复状态,要给View赋对应的ID
  3. 如果需要保存Activity的成员变量,重写方法时,需要保留基类的实现。

4. Activity的启动模式

4.1 LaunchMode

在这里插入图片描述

  1. standard(标准模式)
    在这里插入图片描述
  2. singleTop(栈顶复用模式)
    在这里插入图片描述
    在这里插入图片描述
  3. singleTask(栈内复用模式)
    在这里插入图片描述

如果D所需的任务栈为S1,并且当前任务栈S1的情况为 ADBC,根据栈内复用的原则,此时D不会重新创建,系统会把D切换到栈而并调用onNewIntent 方法,同时由于singleTask 默认具有clearTop的效果,会导致栈内所有在D上面的 Activity全部出栈,于是最终S1中的情况为 AD。这一点比较特殊,在后面还会对此情况详细分析。

  1. singleInstance(单实例模式)
    在这里插入图片描述
    在这里插入图片描述
  • 设置启动模式
//通过在Intent中设置标志位来为Activity指定启动模式
Intent intent = new Intent();
intent.setClass(MainActivity.this,SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

在这里插入图片描述

4.2 复用调用的方法 onNewIntent()

  1. 当ActivityA的LaunchModeSingleTop,并且ActivityA在栈顶,现在启动ActivityA,会调用onNewIntent()方法 。
  • 生命周期顺序为:onResume—>onPause—>onNewIntent—>onResume
  1. 当ActivityA的LaunchModeSingleInstance,SingleTask
  • 如果之前栈内没有它,就会去创建一个它的实例,也就是会调用 onCreate()→onStart()→onResume()
  • 如果之前栈内有它的实例存在的话,生命周期的调用变成了onNewIntent()→onRestart()→onStart()→onResume 。
  • 只对以上的情况,再次启动它们的时候才会调用,即只对startActivity有效。如果仅仅从后台切换到前台而不再次启动的情形,不会触发onNewIntent。
  1. 当ActivityA的LaunchMode为SingleTop,并且ActivityA在栈顶,现在启动ActivityA,会调用onNewIntent()方法 。
  • 生命周期顺序为:onResume—>onPause—>onNewIntent—>onResume
  1. 当ActivityA的LaunchMode为SingleInstance,SingleTask。
    • 如果之前栈内没有它,就会去创建一个它的实例,也就是会调用 onCreate()→onStart()→onResume()
    • 如果之前栈内有它的实例存在的话,生命周期的调用变成了onNewIntent()→onRestart()→onStart()→onResume 。
  • 只对以上的情况,再次启动它们的时候才会调用,即只对startActivity有效。如果仅仅从后台切换到前台而不再次启动的情形,不会触发onNewIntent。
@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);         //设置新的intent
    int data = getIntent().getIntExtra("tanksu", 0);//此时的到的数据就是正确的了
}

5. Activity的TaskAffinity

  • 我们在上文中,多次提到了某个Activity所需的任务栈,什么是Activity所需要的任务栈?这要从一个参数说起:TaskAffinity [afineting] ,可以翻译为任务相关性。这个参数标识了一个Activity所需要的任务栈的名字
  • 如果没有显示指明taskAffinity,那么它的taskAffinity就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于包名
    在这里插入图片描述
android:taskAffinty="com.ning.task1"
  • taskAffinity的作用就是指定想要的任务栈。
  1. 当启动模式设置为standard或singleTop时,taskAffinity是不起作用的。待启动的 Activity 会跟随源 Activity 的任务栈,即使你显式声明了不一样的taskAffinity。
  2. 当启动模式设置了 singleTask或者 singleInstance时,taskAffinity就会新建任务栈来存储待启动的 Activity 实例。

5.1 TaskAffinity和allowTaskReparenting结合

  • TaskAffinity属性主要是用于和allowTaskReparenting属性配对使用。
  • 另外,任务栈分为前台任务栈和后台任务栈,后台任务栈中的Activity位于暂停状态,用户可以通过切换将后台任务栈再调到前台。
  • allowTaskReparenting允许Activity在任务栈之间进行迁移。
    具体点来说,就是一个Activity现在是处于某个Task当中的,但是它与另外一个Task具有相同的affinity值。当另外这个任务切换到前台的时候,该Activity就可以转移到切换到前台的这个任务当中。allowTaskReparenting默认是继承至application中的allowTaskReparenting=false,不可以。
  1. 当一个应用A启动应用B的某个Activity之后,如果这个Activity的allowTaskReparenting属性为true的话。那么当应用B被启动后,此Activity会直接从应用A的任务栈转移到应用B的任务栈中。
  2. 具体一点说就是,比如有两个应用A和B,A启动了B的一个ActivityC,然后按Home 键回到桌面,然后再单击B的桌面图标,这个时候不是启动了B上的 主Activity,而是重新显示了已经被应用A启动的ActivityC。或者说,C从A的任务栈转移到了B的任务栈中。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

5.2 使用FLAG_ACTIVITY_NEW_TASK标记

  • 单独的FLAG_ACTIVITY_NEW_TASK并不等于singleTask,它仅表示寻找Activity所需的任务栈压入。(即TaskAffinity指定的任务栈)
  • FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP 也不等价于启动模式singleTask
  • 当调用startActivity()方法来启动一个Activity时,默认是将它放入到当前的Task(任务)当中。但是,如果在Intent中加入了FLAG_ACTIVITY_NEW_TASK 的话,情况就会变的复杂起来。首先,系统会去检查这个 Activity要求的affinity是否与当前任务栈相同。
  1. 如果相同,把Activity放到当前的Task当中。
  2. 如果不同,先去检查是否有一个名字与该Activity的Affinity相同的Task。
    1. 如果有,这个Task被调到前台,同时将这个Activity显示到这个Task的顶端。
    2. 如果没有,系统将会尝试为这个Activity创建一个新的Task。需要注意的是,如果一个Activity在manifest文件中声明的启动模式是”singleTask”,那么他被启动的时候,行为模式会和前面提到的指定FLAG_ACTIVITY_NEW_TASK一样。

5.3 任务栈和返回栈

  • 任务栈和返回栈是独立存在的。
  1. 任务栈:Activity想要的任务栈,taskAffinity的作用就是指定想要的任务栈,是APP层面的一个东西。
  • 任务栈一般有前台任务栈后台任务栈之分。比如我们手机中打开了飞书,按下Home键之后打开了抖音,此时抖音就在前台任务栈,飞书就在后台任务栈。
  1. 返回栈:它是Activity层面的,用户页面的返回依赖的是返回栈,而不是任务栈。 一个返回栈中可能会包含来自不同任务栈的Activity,返回栈就是为了维护正确的回退栈关系。
    在这里插入图片描述

6. Activity的FLAG

  • 标记位只能在Activity中设置
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  1. FLAG_ACTIVITY_NEW_TASK:这个标记位的作用是为Activity指定"singleTask"启动模式(近似于)。

    • 在不设置taskAffinity的情况下,单独设置FLAG_ACTIVITY_NEW_TASK并没有任何意义,不会创建新的任务栈,每次都会创建新的Activity实例,不会栈内复用。
    • 在一个新的任务栈中启动Activity。如果这个Activity想要的任务栈已经存在,并且其中已经运行着待启动的Activity,那么这个任务栈就会被带到前台,并回调onNewIntent。这个行为和singleTask一致。
  2. FLAG_ACTIVITY_SINGLE_TOP:这个标记位的作用是为Activity指定"singleTop"启动模式,其效果和在XML中指定该启动模式相同

  3. FLAG_ACTIVITY_CLEAR_TOP:具有此标记位的Activity,当它启动时,在同一个任务栈中所有位于它上面的Activity都要出栈。这个标记位一般会和singleTask启动模式一起出现。如果此时被启动的Activity采用standard模式启动,那么它连同它之上的Activity都要出栈,系统会创建新的Activity实例并放入栈顶

    • NEW_TASK+CLEAR_TOP != singleTask,因为在standard模式下启动,会把栈内本身的Activity也删除,所以不等于signleTask。
  4. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:具有这个标识位的Activity不会出现在历史Activity的列表中,当某些情况下我们用户通过历史列表回到我们的Activity的时候这个标记比较有用。他等同于在XML中指定Activity属性:

android:excludeFromRecents="true"
  1. FLAG_ACTIVITY_NO_HOSTORY:被指定的Activity在跳转到其他Activity后,将它从任务栈中移除。

7. IntentFilter

  • 我们知道启动Activity,一般有显示调用和隐式调用两种。显示调用需要明确指定被启动对象的组件信息,包括包名和类名。而隐式调用则不需要。
  • 这里简单介绍一下隐式调用,隐式调用需要Intent能够匹配目标组件的IntentFilter中所设置的过滤信息。
  1. 只有一个Intent同时匹配了action类别、category类别、data类别才算完全匹配,只有完全匹配才能启动目标Activity。
  2. 一个Activity可以有多个IntentFilter,一个Intent只要能匹配任何一组IntentFilter即可成功启动对应的Activity。
    在这里插入图片描述

8. Activity的数据传输

  1. 使用Intent的putExtra传递(传递数据大小有限制,1M左右,根据Binder)
  2. SharedPreference进行数据传递
  3. 使用静态变量传递数据
  4. 使用Bundle对象
  5. 使用Activity销毁时传递数据(onActivityResult)
  6. 使用序列化对象Seriazable

9. Activity的finish()

  • finish()用于结束Activity进程,关闭Activity但不关闭栈。
  • 调用finish()方法后,先pause()当前Activity,会通过AMS的ApplicationThread.scheduleDestroyActivity方法,向ActivtyThread(主线程)发送一个H.DESTROY_ACTIVITY消息
  • 主线程会调用handleDestroyActivity来处理这个消息
  • 在通过层层调用,回调Activity的onDestroy方法。
  • 业务场景
  • 比如在订单列表A点击新建订单进入新建订单ActivityB中,点击保存后,跳转到订单详细C中。在C中我们点击返回键要求返回到A中。

10. 相关问题

10.1 进程模式相关问题

  1. 何谓进程模式?
    在这里插入图片描述

10.2 生命周期相关问题

  1. onPause() 和 onStop()的区别?
    在这里插入图片描述
  2. A启动B,然后B退回A,两者的生命周期变化?
    在这里插入图片描述
  3. 为什么先Activity的onResume()执行,然后才是调用源Activity的onStop()方法呢?
    在这里插入图片描述
  4. MainActivity跳转到DialogActivity(盖不住MainActivity)再跳转到secondActivity的生命周期?
    在这里插入图片描述
  5. 从secondActivity返回到DialogActivity的生命周期?
    在这里插入图片描述
  6. 弹出Dialog对Activity的生命周期有什么影响?
    在这里插入图片描述

10.3 重建机制相关问题

  1. onSaveInstanceState方法调用的时机?
    在这里插入图片描述
  2. 什么时候会发生重建?
    在这里插入图片描述
  3. 为什么会有重建机制?
    在这里插入图片描述
  4. 优先级较低的Activity在内存不足的被回收后,怎样恢复到销毁前的状态?
    在这里插入图片描述

10.4 启动模式相关问题

  1. Activity的启动模式,A是standard,B是singleInstance, A启动B,又启动A会有几个对象?
    在这里插入图片描述
  2. 启动模式和FLAG的区别?
    在这里插入图片描述

10.5 Activity和application有什么区别?

  • Activity是UI界面的抽象,而application是应用程序的抽象。两者都是Context的子类。
  • 应用程序每次启动的时候,系统会为其创建一个application对象且只有一个(单例类),用来存储一些系统的信息,相当于一个容器。
  • 启动application时,系统会创建一个PID(进程ID),所有的Activity都在这个进程上运行,在application创建时会初始化一个全局变量,同一个应用的activity,都可以获取到这个变量。

10.6 onStop和onDestroy()回调延时及延时10S的问题?

为什么回调会延时

  • Activity调用流程:打开ActivityA -> 打开ActivityB -> 关闭ActivityB -> 回到ActivityA
  • 由于要关闭的Activity B或者要打开的Activity A 往主线程的MessageQueue中连续不断地post大量的msg。
  • 导致主线程一直在不断地进行消息循环处理 没有停歇。 因此APP不能向AMS发起IPC来进行ActivityB的销毁。
  • 所以finish ActivityB之后,onDestroy不会被及时回调。具体延时多久,要看主线程中堆积的msg什么时候被处理完。

延时10S

  • Android系统安排了一套流程来保证即使正常流程被阻断以后,ActivityB还是能被销毁。

  • 在关闭Activity B返回Activity A的时候,当AMS侧发起 IPC通知 APP侧的Activity A执行resume的时候,同时也会向AMS自己的主线程发送一个msg,该msg延时10s后执行。

  • 该msg的具体内容与 正常流程APP空闲时段需要执行的任务一致,当然也包括销毁B。

  • 这样Activity B的onDestroy方法也就在延时10s后调用执行。

  • 我们就该在写代码的时候,及时关闭、清理、移除不必要的主线程消息,并且尽可能的保证每个消息处理时间不要太长。

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

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

相关文章

【phaser微信抖音小游戏开发003】游戏状态state场景规划

经过目录优化后的执行结果&#xff1a; 经历过上001&#xff0c;002的规划&#xff0c;我们虽然实现了helloworld .但略显有些繁杂&#xff0c;我们将做以下的修改。修改后的目录和文件结构如图。 game.js//小游戏的重要文件&#xff0c;从这个开始。 main.js 游戏的初始化&a…

集合框架、多线程、IO流

目录 集合框架 Java迭代器&#xff08;Iterator&#xff09; Java集合类 Collection派生 Map接口派生&#xff1a; Java集合List ArrayList Vector LinkedList Java集合Set HashSet LinkedHashSet TreeSet Java集合Queue&#xff08;队列&#xff09; PriorityQue…

AP5101 高压线性恒流电源驱动 输入 24-36V 输出3串18V LED线性恒流驱动方案

1,输入 24V-36V 输出3串18V 直亮 参考BOM 表如下 2,输入 24V-36V 输出3串18V 直亮 参考线路图 如下​ 3&#xff0c;产品描述 AP5101B 是一款高压线性 LED 恒流芯片&#xff0c;外围简单、内置功率管&#xff0c;适用于6- 60V 输入的高精度降压 LED 恒流驱动芯片。最大…

cloudstack之advanced network

cloudstack网络模式的介绍&#xff0c;可参考【cloudstack之basic network】 一、添加资源 访问UI&#xff0c;默认端口为8080&#xff0c;默认用户民和密码是admin/password。点击【continue with installation】。修改默认密码选择zone type&#xff1a;core 选择advanced模…

python中的单引号、双引号和多引号

目录 python中的单引号 python中的双引号 python中的多引号 三者分别在什么时候使用&#xff0c;有什么区别 总结 python中的单引号 在Python中&#xff0c;单引号&#xff08;&#xff09;可以用来表示字符串。 可以使用单引号创建一个简单的字符串&#xff0c;例如&…

cad文件删除了怎么找回来?这7种方法帮你找回

用户咨询&#xff1a;我存在D盘的文件在今天中午突然不见了&#xff1f;全都是些CAD图纸&#xff0c;不知道是不是被我误删了&#xff0c;怎么才能找到这些图纸&#xff0c;对我很重要呢&#xff01;&#xff01;&#xff01; ——CAD文件删除了怎么找回来&#xff1f;误删除了…

测试平台——项目工程创建和配置

这里写目录标题 一、配置开发环境二、配置MySql数据库三、配置工程日志 一、配置开发环境 项目的环境分为开发环境和生产环境。 开发环境:用于编写和调试项目代码。 生产环境:用于项目线上部署运行。 base.py 修改BASE_DIR&#xff1a;拼接.parent 原因&#xff1a;原BASE_D…

数据包在网络中传输的过程

ref: 【先把这个视频看完了】&#xff1a;数据包的传输过程【网络常识10】_哔哩哔哩_bilibili 常识都看看 》Ref&#xff1a; 1. 这个写的嘎嘎好&#xff0c;解释了为啥4层7层5层&#xff0c;还有数据包封装的问题:数据包在网络中的传输过程详解_数据包传输_张孟浩_jay的博客…

ALLEGRO之File

本文主要讨论ALLEGRO软件中的File菜单。 &#xff08;1&#xff09;New&#xff1a;新建&#xff0c;用于新建Board/Package symbol等&#xff1b; &#xff08;2&#xff09;Open&#xff1a;打开&#xff0c;用于打开brd、dra等文件&#xff1b; &#xff08;3&#xff09;S…

C语言题目总结--操作符运用

&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️ &#x1f4a5;个人主页&#xff1a;&#x1f525;&#x1f525;&#x1f525;大魔王&#x1f525;&#x1f525;&#x1f525; &#x1f4a5;代码仓库&#xff1a;&#x1f525;&#x1f525;魔…

【RabbitMQ(day3)】扇形交换机和主题交换机的应用

文章目录 第三种模型&#xff08;Publish/Subscribe 发布/订阅&#xff09;扇型&#xff08;funout&#xff09;交换机Public/Subscribe 模型绑定 第四、第五种模型&#xff08;Routing、Topics&#xff09;第四种模型&#xff08;Routing&#xff09;主题交换机&#xff08;To…

京东LBS推荐算法实践

1、推荐LBS业务介绍 1.1 业务场景 现有的同城购业务围绕京东即时零售能力搭建了到店、到家两种业务场景。同城业务与现有业务进行互补&#xff0c;利用高频&#xff0c;时效性快的特点&#xff0c;可以有效提升主站复访复购频次&#xff0c;是零售的重要战略方向。 1.2 名词…

运行vue项目显示找不到vue-cli

直接下载ruoyi源码到本地&#xff0c;启动ruoyi-ui的时候报错&#xff1a; 原来是电脑没配置nodejs。 所以先去官网下载nodejs&#xff0c;然后安装完之后&#xff0c;在命令行窗口输入&#xff1a; 显示安装成功。 但还没有结束&#xff0c;还要配置npm的全局模块的存放路径…

Apache Doris 巨大飞跃:存算分离新架构

作者&#xff1a;马如悦 Apache Doris 创始人 历史上&#xff0c;数据分析需求的不断提升&#xff08;更大的数据规模、更快的处理速度、更低的使用成本&#xff09;和计算基础设施的不断进化&#xff08;从专用的高端硬件、到低成本的商用硬件、到云计算服务&#xff09;&…

高忆管理:k线分析股票走势?

K线是一种经典的技术剖析工具&#xff0c;经过制作股票价格的收盘、开盘、最高和最低价&#xff0c;形成实体和影线&#xff0c;以反映股票价格的动摇和趋势。本文将从多个角度剖析K线剖析股票走势的重要性及使用。 1. 提醒价格趋势 K线图能够清晰显现股票价格走势的趋势&…

性能测试必须掌握的知识点:并发和并行以及CPU的状态和核心参数

性能测试一定绕不开并发和并行&#xff0c;而并发和并行又离不开CPU&#xff0c;本文就来带大家深入理解一下究竟什么是并发和并行以及CPU的状态和核心参数。 并发和并行 通常情况下&#xff0c;CPU 有几个核&#xff0c;就可以并行执行几个进程&#xff08;线程&#xff09;…

00 - RAP 开发环境配置

文章目录 [1] Eclipse - ADT[2] BTP / S4HC[3] Add ABAP Env. Service[4] Conn. to BTP [1] Eclipse - ADT 关于如何安装配置&#xff0c;参见文章: Install ABAP Development Tools (ADT) and abapGit Plugin Eclipse Eclipse - ADT Eclipse - abapGit Plugin [2] BTP / S4…

Linux 安装软件 - yum工具

在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的软件包, 直接进行…

大龄青年的浙大MBA读书梦——提面优秀190+的上岸经验分享

时间如白驹过隙&#xff0c;三十年的岁月也转瞬即逝&#xff0c;回首过往这三十年的人生路&#xff0c;没有大起大落&#xff0c;一直都是相对比较平稳。但这几年疫情原因&#xff0c;公司效益不好&#xff0c;不仅我们公司整个行业也都在裁员&#xff0c;为了让自己更具备竞争…

Camtasia2023喀秋莎中文版视频编辑软件

Camtasia专业的 屏幕录制和视频剪辑软件 3000多万专业人士在全球范围内使用Camtasia展示产品&#xff0c;教授课程&#xff0c;培训他人&#xff0c;以更快的速度和更吸引人的方式进行沟通和屏幕分享。使您在Windows和Mac上进行录屏和剪辑创作专业外观的视频变得更为简单。 喀秋…