活动的四种启动模式详解

2023-05-16

android:launchMode

目录

  • android:launchMode
  • 前言
  • 概念说明
    • standard
    • singleTop
    • singleTask
    • singleInstance
  • Codes演示
    • 说明
    • standard代码
    • singleTop代码
    • singleTask代码
    • singleInstance代码

前言

本文部分内容参考了郭神的《第一行代码》

活动的启动模式一般在AndroidManifest.xml中定义标签android:launchMode=" "
接下来开始具体介绍这四个启动模式的区别以及用途
standard singleInstance singleTop singleTask

1
说到这,我们先来看看返回栈是个什么呢?

原文是这样的:Android是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的活动的集合,这个栈被称为返回栈(Back Stack)。
理解:现在我们有一堆活动,activity(简称a),a1,a2,a3,a4,…,an,然后把这些活动都存在返回栈中.最先入栈的a1就在栈底,最后入栈的an就在栈顶,那么这些活动每次工作时,就会出栈入栈,整个流程如下图:

1
说实在的,我还是觉得上图有点点抽象,再来张新图理解一下子。
1

概念说明

standard

标准模式:这是Android默认模式,当AndroidManifest中不声明时的模式。首先,Android通过返回栈来管理活动的(栈的特点就是先进后出,就像一个罗汉塔,最先取出栈顶的数据)。每当我们启动一个新的活动时,这个新活动就会进入返回栈,处于栈顶。每新建一次,它就会往栈顶堆一个活动,它不会去看这个栈是否已经存在这个活动。

这里我们不妨把活动看成下面的小星星,串呢就是一个返回栈。我们每启动一个新活动,就串一个小星星,我们不会去管下面那个是不是相同的,只会一直串。串了之后要返回呢,我们就只能一个一个地去返回,就是把上面 的小星星一个一个取出来。
2
standard的模式示意图如下(摘自郭神的《第一行代码》):
2
所以像上诉的情况,当你点击button2次时,你要按3次返回键才能退出最开始的活动。而且这个模式下每启动一次活动就会新建一次,但是它也有它的运用。上面只是为了演示,通常app不会从现在活动跳转到现在的活动

应用场景:大部分app应用,因为一般都不会在当前活动反复横跳。

singleTop

在这种模式下,比如启动活动A时,发现返回栈的栈顶就是活动A,那么就可以直接使用它,而不用创建新的活动实例。

还是将活动看成串串上的串,那么如下图示例
1

所以像上诉的情况,当你点击button2次时,你点击一次返回键就退出了app。但是如果栈顶元素不是该活动,它还是会创建新的活动。
应用场景:大部分app应用,或者浏览器或者今日头条等新闻推送。
比如你进入手机浏览器,我点了个新冠查看,然后一不小心点了个返回主页,然后我点击返回,它又返回新冠页面了。
如下图,我先从主页面点击搜索框进入搜索页面,查看新冠疫情状况,然后点击底部直接回到主页面,不用点击它出现的那个返回的那个标志,直接手机返回,我的是屏幕手指左滑或者右滑就行,然后就又返回到了新冠页面,再次点击返回,又回到了搜索页面,再返回,进入原先的主页面,整个过程如下图。(主页面貌似有广告会违规,然后去掉那些广告图,直接看底部导航栏)
1

1

singleTask

singleTop虽然解决了大量重复创建栈顶活动的问题,但是目标活动不位于栈顶时,依然会创建大量重复的活动占用内存。singleTask模式很好滴解决了这个问题,每次启动目标活动时,系统会在返回栈中去搜寻是否已经存在该活动,如果存在,就把栈中位于该活动上方的活动全部出栈,如果没有再创建新的。

s
然后你发现,当再来一个新活动(是蓝色菱形)时,因为前面的活动已经出栈了,所以会创建新的活动

应用场景:购物页面,比如淘宝、拼多多、京东等购物app。
当从首页搜索后,进入商品浏览页,进入商品详情页面之后,点击购买,然后跳转至付款页面,付完款后购买成功,点击button又可以直接返回到首页,也即是说,商品浏览页,商品详情页,付款页出栈,button直接导向首页。

singleInstance

singleInstance会启用新的返回栈(stack)来管理活动。为什么这么干呢?
首先从字面来看,它是单一实例模式。也即是说Activity单独占用一个任务栈,而且由于栈内复用的特性,后续的请求不会再创建新的Activity实例,除非这个任务栈被销毁(destroy())
目标活动(给它取个名叫special)有了单独的栈来存放自己,这样当程序A想来调用special,程序B想调用它,程序C还想调用它时,程序之间共享此活动的实例在这个模式下就能很容易地实现了。而每个应用程序都有自己的返回栈,所以前三种模式并不能解决共享活动实例的问题,singleInstance模式就能起到很大的作用了。

参考引用 :按照惯例,先放一张引用自《第一行代码》的模式示意图。
1

图解

有3个不同的进程(返回栈),可以看到,当活动启动方式为singleInstance的时候,就可以实现不同的程序共享同一个实例。
对于返回栈1:粉色箭头代表启动活动,蓝色代表返回,那么返回的顺序会如下图所示。因为活动1.1,1。2,1.3和活动优秀不在同一个栈中,所以优先返回自己所在栈中的活动,最后切回优秀
1

应用场景: 一些系统应用,比如日程、电话、系统通讯录、闹钟、相册等等。
在QQ或者微信或者支付宝都要打开相册,打开的都是相册那个页面。

Codes演示

说明

来说说代码咋个写。File --> New -->New Project,选择Empty Activity
然后,我们就拥有了一个mainActivity,现在再在com.example.xx包下再建立2个Activity,分别取名为SecondActivity和ThirdActivity,对应的Layout里面放上一个Button.
可以通过打印日志来进行理解活动不同启动模式下的差异

standard代码

MainActivity
这里其它的Activity暂时不用改变,或者你先只创建这么一个activity,standard模式演示。android默认模式

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, this.toString());
        Log.d(TAG, "Task id is" + getTaskId());//打印当前返回栈
        setContentView(R.layout.activity_main);
        Button but1 = findViewById(R.id.button_1);
        but1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });
    }
}

你点击n次but1,会发现退出app需要点击n+1次返回键。

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button1"
        android:textAllCaps="false"/>

</LinearLayout>

singleTop代码

看过来,把AndroidManifest.xml,就是本文的第一张图的那个launchmode后面改成singleTop

其他部分代码不变,如上standard,然后你会发现, 不管你开始点击多少次button1按钮,最终你点击一次返回就能够退出程序了。但是呢,当栈顶元素不是该活动时,仍然会有新的活动入栈。就是栈顶元素不是它时,当再次启动它的时候还是会创建一个新的它,所以当跳转多个不同的页面时,效果和standard就很相似。

现在你继续修改代码,从界面1跳转至界面2,再点击button2,跳转到界面1,然后你点击返回,它会先返回到界面2,再点击返回再返回到界面1,再点击返回最后退出,会发现这个返回和standard就很相似了。因为都是不同的活动,所以每启动新的活动时,依旧会创建新活动入栈。

AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.test4">

    <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.Test4">
        <activity android:name=".ThirdActivity"
            android:exported="true"
            android:label="Third"/>
        <activity
            android:name=".SecondActivity"
            android:exported="true"
            android:label="Sec"
            android:launchMode="singleTop"/>
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="Main"
            android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

MainActivity

package com.example.test4;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, this.toString());
        Log.d(TAG, "Task id is" + getTaskId());//打印当前返回栈
        setContentView(R.layout.activity_main);
        Button but1 = findViewById(R.id.button_1);
        but1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                startActivity(intent);
            }
        });
    }
    @Override
    protected void onRestart(){
        super.onRestart();
        Log.d(TAG, "onRestart");
    }
}

activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button1"
        android:textAllCaps="false"/>

</LinearLayout>

SecondActivity

package com.example.test4;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class SecondActivity extends AppCompatActivity {
    private static final String TAG = "SecondActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, this.toString());
        Log.d(TAG, "Task id is" + getTaskId());
        setContentView(R.layout.activity_second);
        Button button2 = findViewById(R.id.button_2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(SecondActivity.this,FirstActivity.class);
                startActivity(intent);
            }
        });
    }
    @Override
    protected void onDestroy(){
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }
}

activity_second.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SecondActivity">
    <Button
        android:id="@+id/button_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button2"
        android:textAllCaps="false"/>

</LinearLayout>

singleTask代码

这里你会发现,当你点击button从页面1跳转到页面2,再点击页面2的按钮跳转到页面1,按一下返回键就可以退出程序了。

MainActivity

package com.example.test4;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, this.toString());
        Log.d(TAG, "Task id is" + getTaskId());//打印当前返回栈
        setContentView(R.layout.activity_main);
        Button but1 = findViewById(R.id.button_1);
        but1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                startActivity(intent);
            }
        });
    }
    @Override
    protected void onRestart(){
        super.onRestart();
        Log.d(TAG, "onRestart");
    }
}

xml不发生改变
SecondActivity

package com.example.test4;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class SecondActivity extends AppCompatActivity {
    private static final String TAG = "SecondActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, this.toString());
        Log.d(TAG, "Task id is" + getTaskId());
        setContentView(R.layout.activity_second);
        Button button2 = findViewById(R.id.button_2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(SecondActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });
    }
    @Override
    protected void onDestroy(){
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }
}

second.xml不发生改变
AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.test4">

    <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.Test4">
        <activity android:name=".ThirdActivity"
            android:exported="true"
            android:label="Third"/>
        <activity
            android:name=".SecondActivity"
            android:exported="true"
            android:label="Sec"
            android:launchMode="singleTask"/>
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="Main"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

singleInstance代码

这里因为secondActivity模式设置为了singleInstance,所以MainActivity和ThirdActivity在一个返回栈中,2号单独在一个栈中。所以你会发现,当你点击按钮1到达页面2,再点击button2到达页面3,点击返回键时,你会回到页面1去,再点击返回键回到页面2,再点击返回退出app。

MainActivity.java

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, this.toString());
        Log.d(TAG, "Task id is" + getTaskId());//打印当前返回栈
        setContentView(R.layout.activity_main);
        Button but1 = findViewById(R.id.button_1);
        but1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                startActivity(intent);
            }
        });
    }
    @Override
    protected void onRestart(){
        super.onRestart();
        Log.d(TAG, "onRestart");
    }
}

SecondActivity.java

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class SecondActivity extends AppCompatActivity {
    private static final String TAG = "SecondActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, this.toString());
        Log.d(TAG, "Task id is" + getTaskId());
        setContentView(R.layout.activity_second);
        Button button2 = findViewById(R.id.button_2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(SecondActivity.this,ThirdActivity.class);
                startActivity(intent);
            }
        });
    }
    @Override
    protected void onDestroy(){
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }
}

ThirdActivity.java

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;

public class ThirdActivity extends AppCompatActivity {
    private static final String TAG = "ThirdActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "Task id is" + getTaskId());
        setContentView(R.layout.activity_third);
    }
}

androidmanifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.test4">

    <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.Test4">
        <activity android:name=".ThirdActivity"
            android:exported="true"
            android:label="Third"/>
        <activity
            android:name=".SecondActivity"
            android:exported="true"
            android:label="Sec"
            android:launchMode="singleInstance"/>
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="Main">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button1"
        android:textAllCaps="false"/>

</LinearLayout>

activity_second.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SecondActivity">
    <Button
        android:id="@+id/button_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button2"
        android:textAllCaps="false"/>
        
</LinearLayout>

activity_third.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ThirdActivity">

    <TextView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_marginStart="52dp"
        android:layout_marginLeft="52dp"
        android:layout_marginTop="340dp"
        android:text="Hello,smart person !!!"
        android:textSize="36sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

活动的四种启动模式详解 的相关文章

  • 【GStreamer 】2-ubuntu v4l2-ctl 查看USB 相机基本参数

    v4l2是Video4linux2的简称 xff0c 是linux中关于视频设备的内核驱动 xff0c 在Linux中 xff0c 视频设备是设备文件 xff0c 可以像访问普通文件一样对其进行读写 xff0c 摄像头设备文件位置是 dev
  • 使用conda安装Paddle3D时出现的报错及解决方式

    1 cmake时 usr bin ld cannot find lxxx问题 如 xff1a usr bin ld cannot find lleveldb usr bin ld cannot find lsnappy 解决方法 xff1a
  • git安装及使用常用命令

    1 安装 Ubuntu xff1a apt get install git Windows xff1a 官网下载地址 xff1a https gitforwindows org xff0c 也可以用国内镜像 xff1a https npm
  • 如何设置才能提升VMware虚拟机的显卡性能

    将本机的intel和NVIDIA显卡驱动更新为最新版本 使用最新的VMware Workstation pro 12 5 处理器中 xff0c 选择8个核心 xff0c 勾选下面两个虚拟化
  • 程序设计思维与实践 CSP-M3 补题 (3/4/数据班)

    程序设计思维与实践 CSP M3 A csp m3 t1题目分析代码 B csp m3 t2题意分析代码 T4 咕咕东学英语题意 分析代码 A csp m3 t1 题目 瑞神的数学一向是最好的 xff0c 连强大的咕咕东都要拜倒在瑞神的数学
  • Centos7搭建Samba文件共享服务

    编辑本地yum源 root 64 localhost vim etc yum repos d local repo Centos7 name 61 CentOS Local baseurl 61 file mnt gpgcheck 61 0
  • IS-IS协议原理与配置

    IS IS 中间系统到中间系统协议 xff1a 基于链路状态并使用最短路径优先算法进行路由计算的一种IGP协议 基于802 3封装 IS IS最初是国际化标准组织ISO为它的无连接网络协议CLNP设计的一种动态路由协议 为了提供对IP的路由
  • 数据库关系代数表达式学习

    一 关系代数的9种操作 xff1a 关系代数中包括了 xff1a 并 交 差 乘 选择 投影 联接 除 自然联接等操作 五个基本操作 xff1a 并 差 笛卡尔积 投影 选择 四个组合操作 xff1a 交 联接 等值联接 自然联接 RS 除
  • 手把手教你从阿里云到idea的短信服务怎么玩.给你女朋友发一条是不是贼帅?

    短信服务 1 1打开阿里云 创建成功就会有 总结阿里云 1 开启子用户 2 新建用户组 设置添加权限 3 创建一个用户 具体用来操作的账号 4 得到AccessKey id 密码 61 61 注意 保存账号 61 61 如果泄露 用户组下禁
  • week16——实验(csp_m4)

    目录 TT数鸭子 xff1a 问题描述题目简述输入 输出格式样例 问题分析解题思路参考代码 心得体会 ZJM要抵御宇宙射线 xff1a 问题描述题目简述输入 输出格式样例 问题分析解题思路参考代码 心得体会 宇宙狗的危机 xff1a 问题描
  • Gstreamer 应用开发:1-基础介绍

    我们之前的系列 xff0c 正式的介绍了Gstreamer xff0c 并且围绕如何使用USB相机推流实现RTSP服务器来做了介绍 xff0c 并在Jeston TX1 平台上做了优化急速的一些探索 今天我们开始围绕如何用命令实现一个音视频
  • 【蓝桥杯】单片机学习(3)——数码管的显示+定时器+中断

    数码管 43 定时 43 中断 一 定时器1 定时器基础知识2 定时器的寄存器 xff08 TCON amp TMOD xff09 3 定时器的应用 二 中断1 中断的概念2 51单片机内与中断控制有关的寄存器3 中断的响应条件及应用 三
  • 什么是程序的耦合

    耦合性 Coupling xff0c 也叫耦合度 xff0c 它是对模块间关联程度的度量 在软件工程中 xff0c 耦合指的就是对象之间的依赖关系 对象之间的耦合越高 xff0c 则表明模块的独立性和可复用性越差 xff0c 且维护成本越高
  • 对比BeanFactory和ApplicationContext的关系

  • JDBC的API----Connection

    作用 xff1a 1 获取执行sql的对象 2 管理事务 获取连接对象 Connection conn 61 DriverManager getConnection String url String name String passwor
  • 数据库连接池----Druid

    数据库连接池的标准接口 xff1a DataSource 获取连接的方法 xff1a Connection getConnection Druid是Java最好的数据库连接池之一 Druid数据库连接池的使用步骤 xff1a 1 导入jar
  • Java--IP地址操作类----InetAddress

    此类表示IP地址 InetAddress API xff1a public class InetAddressDemo01 public static void main String args throws IOException 1 获
  • MyBatis----映射文件概述

    创建映射文件时一定要给映射文件添加约束头 xff0c 约束头相对固定 xff0c 可以直接复制 xff1a lt xml version 61 34 1 0 34 encoding 61 34 UTF 8 34 gt lt DOCTYPE
  • 如何使用MyBatis

    1 创建user表 xff0c 添加数据 CREATE DATABASE mybatis USE mybatis DROP TABLE IF EXISTS tb user CREATE TABLE tb user id INT PRIMAR

随机推荐

  • Mapper代理开发

    1 定义与SQL映射文件同名的Mapper接口 xff0c 并且将Mapper接口和SQL映射文件放置在同一目录下 2 设置SQL映射文件的namespace属性为Mapper接口的全限定名 lt mapper namespace 61 3
  • Windows连接远程Ubuntu RDP

    一 配置远程Ubuntu 1 安装 TrigerVNC Server sudo apt install tightvncserver 2 安装xrdp sudo apt install xrdp 查看运行状态 sudo systemctl
  • 【EHub_tx1_tx2_E100】Ubuntu18.04 + ROS_ Melodic + 银牛R132深度相机(如何在该环境下打开摄像机获取rgb/深度图/点云)

    简介 xff1a 介绍银牛微电子 3D 机器视觉R132相机 在EHub tx1 tx2 E100载板 xff0c TX1核心模块环境 xff08 Ubuntu18 04 xff09 下测试ROS驱动 xff0c 打开摄像头图像和查看深度图
  • week5 作业B TT's Magic Cat

    TT s Magic Cat Thanks to everyone s help last week TT finally got a cute cat But what TT didn t expect is that this is a
  • week8 CSP模拟C 咕咕东的奇妙序列

    咕咕东的奇妙序列 有一个序列11212312341234512345612345671234567812345678912345678910 特点为由若干部分组成 每一部分si为1 i所有数字 给出q q lt 61 500 次查询 每次查
  • week9 作业B 东东学打牌

    东东学打牌 最近 xff0c 东东沉迷于打牌 所以他找到 HRZ ZJM 等人和他一起打牌 由于人数众多 xff0c 东东稍微修改了亿下游戏规则 xff1a 所有扑克牌只按数字来算大小 xff0c 忽略花色 每张扑克牌的大小由一个值表示 A
  • week11 E - 选做题11-1 东东与 ATM

    选做题11 1 东东与 ATM 一家银行计划安装一台用于提取现金的机器 机器能够按要求的现金量发送适当的账单 机器使用正好N种不同的面额钞票 xff0c 例如D k xff0c k 61 1 2 N xff0c 并且对于每种面额D k xf
  • week13 C - TT 的奖励(必做)

    TT 的奖励 xff08 必做 xff09 在大家不辞辛劳的帮助下 xff0c TT 顺利地完成了所有的神秘任务 神秘人很高兴 xff0c 决定给 TT 一个奖励 xff0c 即白日做梦之捡猫咪游戏 捡猫咪游戏是这样的 xff0c 猫咪从天
  • 程序设计作业之C - 掌握魔法の东东 I和D-数据中心

    程序设计作业 C 掌握魔法 东东 ID 数据中心 C 掌握魔法 东东 I 东东在老家农村无聊 xff0c 想种田 农田有 n 块 xff0c 编号从 1 n 种田要灌氵 众所周知东东是一个魔法师 xff0c 他可以消耗一定的 MP 在一块田
  • 程序设计之B - 东东学打牌(C++

    目录 题目大致题意解题分析测试数据 xff08 全面代码 题目 题面 最近 xff0c 东东沉迷于打牌 所以他找到 HRZ ZJM 等人和他一起打牌 由于人数众多 xff0c 东东稍微修改了亿下游戏规则 xff1a 所有扑克牌只按数字来算大
  • Week11 C-必做题 11-3

    题目 Julius Caesar 曾经使用过一种很简单的密码 对于明文中的每个字符 xff0c 将它用它字母表中后 5 位对应的字符来代替 xff0c 这样就得到了密文 比如字符 A 用 F 来代替 如下是密文和明文中字符的对应关系 密文A
  • NO.4模测之TT数鸭子

    TT数鸭子 时间限制 空间限制 1S 256MB 题目描述 这一天 TT因为疫情在家憋得难受 在云吸猫一小时后 xff0c TT决定去附近自家的山头游玩 TT来到一个小湖边 看到了许多在湖边嬉戏的鸭子 xff0c T顿生羡慕 此时他发现每一
  • PS2020安装时出现184错误解决办法(详细步骤

    首先一些之前安装过Photoshop 的伙伴们再次安装就会出现 184错误 xff0c 那么如何解决涅 xff1f 见如下步骤 亲测有效 1 打开C programfiles commonfiles 找到adobe文件夹 xff0c 把它删
  • 【ROS2 入门】虚拟机环境 ubuntu 18.04 ROS2 安装

    大家好 xff0c 我是虎哥 xff0c 从今天开始 xff0c 我将花一段时间 xff0c 开始将自己从ROS1切换到ROS2 xff0c 做为有别于ROS1的版本 xff0c 做了很多更新和改变 xff0c 我还是很期待自己逐步去探索R
  • 如何在Markdownpad2中显示数学公式

    前言 说句实话 xff0c 我觉得markdown比LaTeX方便多了 xff0c 但是就是数学公式方面太麻烦了 xff0c 所以只好想方设法找办法 Markdown pad2的安装 如果你还没有安装markdownpad2的话 xff0c
  • 如何在其他盘安装office

    office 2019安装详细过程 把office安装在D盘 目录 office 2019安装详细过程把office安装在D盘前言声明下载Office准备工作正式安装Office的时刻到了无法安装 xff0c 错误 xff0c 需要重启 x
  • 接口回调(笔记

    接口回调讲解 回调定义回调机制回调意义接口回调的实现步骤参考 网上看了一堆 xff0c 感觉有点零散 xff0c 我自己总结一下 看评论区说存在很多问题 xff0c 我读了一下 xff0c 雀氏存在一些 xff0c 非常感谢批评指正 xff
  • Weka下载安装详解

    目录 前言Weka下载Weka安装Weka启动 前言 如果你没有安装Java的话 xff0c 请看这里 xff0c 选择合适的Java版本 xff0c 这里我选用的是java11 选择jdk8也可以 xff0c 它有jre xff0c 11
  • Android Studio安装教程

    Android Studio详细安装教程 1 Java环境配置2 Android Studio的安装 1 Java环境配置 这里Android开发基于Java语言 xff0c 所以先配置Java环境 首先选择合适的jdk版本 xff0c 随
  • 活动的四种启动模式详解

    android launchMode 目录 android launchMode前言概念说明standardsingleTopsingleTasksingleInstance Codes演示说明standard代码singleTop代码si