Android之 activity活动页面详解

news2024/11/27 2:15:08

一 四大组件

1.1 Activity组件,它一个单独的窗口,程序流程都必须在Activity中运行,所有它是最基本的模块。

1.2 service组件,用于在后台完成用户指定的操作。

1.3 content provider组件,会为所有的应用准备一个内容窗口,并且保留数据库、文件。

1.4 broadcast receiver组件,是程序之间传递信息时的一种机制,作用就是接收或者发送通知。

二 Activity简介

2.1 Activity是四大组件中用的最多的,是数据显示的载体,也是用户视觉显示和行为操控的界面。

2.2 一个程序包含一个或者多个Activity,Activity之间的跳转和数据通信依赖于Intent(意图)。

三 Activity的创建

3.1 Actvity是一个Java类,先创建一个Class,继承于Activity或者

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

3.2 创建xml布局文件

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

     ...................    

</FrameLayout>

3.3 在清单文件AndroidManifest.xml注册Activity组件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">
    <uses-permission android:name="android.permission.INTERNET" />
    <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.MyApplication">
        <activity
            android:name=".MainActivity"
            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.5 Intent启动组件

Intent intent = new Intent(this,MainActivity.class);
startActivity(intent);

四 Context上下文

4.1 很多人刚接触Context不太理解是干什么用的,上下文又是什么意思。Context其实是一个程序运行的环境,在这个环境里面可以做四大组件的启动,页面的跳转,资源的访问。总结起来就是应用程序和系统之间的桥梁,应用程序访问系统各种资源的接口

4.2 Context种类也不止一种,虽然都可以去访问系统资源,但各自的生命周期不一样。可以细分为以下三类:Application,Activity,service

4.3  生命周期的对比

Application的生命周期是最长的,一般应用不杀死就会一直存在。

Activity和Service的生命周期比较短,所以内存泄漏大部分发生在这两种Context的引用上面

4.4 Context使用场景对比

五 Activity生命周期

5.1 生命周期图示

5.2 如下复写Activity的生命周期 

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //当Activity第一次被创建的时候调用此方法.一般在此方法中进行控件的声明,添加事件等初始化工作.
    }

    @Override
    protected void onStart() {
        super.onStart();
        //当Activity被显示到屏幕上的时候调用此方法.
    }

    @Override
    protected void onResume() {
        super.onResume();
        //当此Activity能够被操作之前,也就是能够获得用户的焦点之前调用此方法.
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        //当Activity被停止后又被再次启动之前调用此方法.接着将调用onStart()方法.
    }

    @Override
    protected void onPause() {
        super.onPause();
        //当第一个Activity通过Intent启动第二个Activity的时候,将调用第一个Activity的onPause()方法.然后调用第二个Activity的onCreate(),onStart(),onResume()方法,接着调用第一个Activity的onStop()方法.如果Activity重新获得焦点,则将调用onResume()方法;如果此Activity进入用户不可见状态,那么将调用onStop()方法
    }

    @Override
    protected void onStop() {
        super.onStop();
        //当第一个Activity被第二个Activity完全覆盖,或者被销毁的时候回调用此方法.如果此Activity还会与用户进行交互,将调用onRestart方法();如果此Activity将被销毁,那么将调用onDestroy()方法.
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //Activity被销毁之前调用此方法.或者是调用finish()方法结束Activity的时候调用此方法.可以在此方法中进行收尾工作,比如释放资源等.
    }
}

5.3 比如两个Activity,AActivity.java和BActivity.java

打开AActivity,生命周期如下:

AActivity onCreate() ->  AActivity onStart() -> AActivity onStart()

从AActivity跳转BActivity,生命周期如下:

AActivity onPause() -> BActivity oncreate() -> BActivity onstart() -> BActivity onresume() -> AActivity onstop()

从BActivity返回AActivity,生命周期如下:

BActivity onPause() -> AActivity onRestart() -> AActivity onStart() -> AActivity onResume() -> BActivity onStop() -> BActivity onDestroy()

5.4  Activity启动模式

  • standard:默认启动模式,每次激活activity时,都创建activity实例,并放入任务栈。
  • singleTop: 如果某个Activity自己激活自己,即任务栈栈顶是该Activity,则不需要创建,其余情况都要创建Activity。
  • singleTask:如果要激活的activity在任务栈中,则不需要创建,只需要把这个Activity放入栈顶,并把该Activity以上的Activity实例都出栈。
  • singleInstance:只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的Activity存在。

 设置启动模式两种方式:

静态设置:

<application
	android:allowBackup="true"
	android:icon="@mipmap/ic_launcher"
	android:label="@string/app_name"
	android:supportsRtl="true"
	android:theme="@style/Theme.MyApplication">
	<activity
		android:name=".MainActivity"
		android:launchMode="standard"
		android:exported="true">
		<intent-filter>
			<action android:name="android.intent.action.MAIN" />

			<category android:name="android.intent.category.LAUNCHER" />
		</intent-filter>
	</activity>
	<activity android:name=".Activity2"
		android:launchMode="singleTop"/>

	<activity android:name=".Activity3"
		android:launchMode="singleTask"/>

	<activity android:name=".Activity4"
		android:launchMode="singleInstance"/>
</application>

动态设置:

//默认不设置,即standard
Intent intent = new Intent(this,MainActivity.class);
startActivity(intent);

//FLAG_ACTIVITY_SINGLE_TOP,即singleTop
Intent intent2 = new Intent(this,Activity2.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent2);

//FLAG_ACTIVITY_CLEAR_TOP,即singleTask
Intent intent3 = new Intent(this,Activity3.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent3);

//FLAG_ACTIVITY_NEW_TASK,即singleInstance
Intent intent4 = new Intent(this,Activity4.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent4);

六 Intent意图

6.1 前面说过Intent也非常重要,是连接组件的桥梁,用来启动activity, service和broadcast receiver和组件之间的通信,而Content Provider本身就是一种通信机制,不需要通过Intent。

6.2 Intent启动组件

  • 使用Context.startActivity() 或 Activity.startActivityForResult(),传入一个intent来启动一个activity。使用 Activity.setResult(),传入一个intent来从activity中返回结果。
  • 将intent对象传给Context.startService()来启动一个service或者传消息给一个运行的service。将intent对象传给 Context.bindService()来绑定一个service。
  • 将intent对象传给 Context.sendBroadcast(),Context.sendOrderedBroadcast(),或者Context.sendStickyBroadcast()等广播方法,则它们被传给 broadcast receiver

6.3 Intent的属性

  • component(组件):目的组件,一般是类名完整路径(包名.类名)
  • action(动作):用来表现意图的行动
  • category(类别):用来表现动作的类别
  • data(数据):表示与动作要操纵的数据
  • type(数据类型):对于data范例的描写
  • extras(扩展信息):扩展信息
  • Flags(标志位):期望这个意图的运行模式

根据不同的属性设置,启动Activity分为显式和隐式:

  • 显式即直接启动,明确指向一个Activity类组件。
  • 隐式指间接启动,根据action,category,data等筛选查找到匹配的组件。

6.4 显式启动的三种方式:

方式一:直接启动

Intent intent = new Intent(this,MainActivity.class);
startActivity(intent);

方式二:setComponent新建组件启动

Intent intent = new Intent();
intent.setComponent(new ComponentName(this, MainActivity.class);)
startActivity(intent);

方式三:setClassName设置全Activity全路径

Intent intent = new Intent();
intent.setClassName(this,"com.dinghe.schemetestmain.MainActivity");
startActivity(intent);        

6.5 隐式启动设置Action:

方式一:设置Action

如调用系统程序,系统Action

Intent intent = new Intent();
拨打电话
intent.setAction(Intent.ACTION_CALL);
发送短信
intent.setAction(Intent.ACTION_SENDTO);
打开相机
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
//启动
startActivity(intent);

方式二:如自定义Action,在AndroidManifest.xml里面设置intent-filter的Action

<activity
	android:name=".ActionActivity"
	android:exported="true">
	<intent-filter>
		<action android:name="com.dinghe.schemetest.customerAction"/>
		<category android:name="android.intent.category.DEFAULT" />
   </intent-filter>
</activity>
Intent intent = new Intent();
intent.setAction(getPackageName()+".customerAction");
startActivity(intent);

方式三:设置action+data,打开网站:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));                
startActivity(intent);

方式四:设置action+data+type,打开指定类型文件

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri data = Uri.parse("file:///storage/sdcard0/test.mp3");
//设置data+type属性
intent.setDataAndType(data, "audio/mp3"); //方法:Intent android.content.Intent.setDataAndType(Uri data, String type)
startActivity(intent);  

方式五:设置action+category+data+extra+flags

Intent intent = new Intent();
intent.setAction(Intent.ACTION_SENDTO);
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse("smsto:"+"10086"));
intent.putExtra("keyName","keyValue");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

注意: 如果自己定义的某个Action要通过隐式启动,在AndroidManifast.xml中必须加上 android.intent.category.DEFAULT,否则不起作用

七 Activity间通信

7.1 Activity传递数据要用到Intent.putExtra()方法,里面可以传递任意类型的数据,如下图所示传递基本类型,数组类型,字节类类型

集合类型,和Bundle类型 

 

 7.2 Intent传递数据

Intent intent = new Intent(this,MainActivity.class);
intent.putExtra("intKey",1);
intent.putExtra("StringKey","111");
startActivity(intent);

7.3 Bundle传递数据

Intent intent = new Intent(this,MainActivity.class);
Bundle bundle=new Bundle();
bundle.putInt("intKey",1);
bundle.putString("StringKey","111");
intent.putExtras(bundle);
startActivity(intent);

Activity启动流程

1. Launcher进程请求AMS

2. AMS发送创建应用进程请求

3. Zygote进程接受请求并孵化应用进程

4. 应用进程启动ActivityThread

5. 应用进程绑定到AMS

6. AMS发送启动Activity的请求

7. ActivityThread的Handler处理启动Activity的请求

 

九  Activity管理和回退

9.1 监听程序的后台和前台切换,如返回桌面和从桌面打开的状态。

利用Application.ActivityLifecycleCallbacks的方法,全局监听Activity的打开数量,数量0表示在后台,大于1表示前台

如下前后台监听的具体实现:

private Application.ActivityLifecycleCallbacks activityLifecycleCallbacks = new Application.ActivityLifecycleCallbacks() {
	//打开的Activity数量统计
	private int activityStartCount = 0;

	@Override
	public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

	}

	@Override
	public void onActivityStarted(Activity activity) {
		activityStartCount++;
		//数值从0变到1说明是从后台切到前台
		if (activityStartCount == 1) {
			//从后台切到前台
			
		}
	}

	@Override
	public void onActivityResumed(Activity activity) {

	}

	@Override
	public void onActivityPaused(Activity activity) {

	}

	@Override
	public void onActivityStopped(Activity activity) {
		activityStartCount--;
		//数值从1到0说明是从前台切到后台
		if (activityStartCount == 0) {
			//从前台切到后台
			
		}
	}

	@Override
	public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

	}

	@Override
	public void onActivityDestroyed(Activity activity) {

	}
};

9.2 定义Activity回退栈,在Activity的onCreate里面添加进栈,可以在任意页面来结束指定页面或者全部页面

如下新建Activity栈的管理工具类:

public class ActivityUtil {
    public static Stack<Activity> activityStack = new Stack<Activity>();

    /**
     * 添加Activity到堆栈
     */
    public static void addActivity(Activity activity) {
        activityStack.push(activity);
    }

    public static void removeActivity(Activity activity) {
        activityStack.remove(activity);
    }

    /**
     * 获取当前Activity(堆栈中最后一个压入的)
     */
    public static Activity currentActivity() {
        return activityStack.lastElement();
    }

    /**
     * 结束当前Activity(堆栈中最后一个压入的)
     */
    public static void finishCurrentActivity() {
        Activity activity = activityStack.pop();
        activity.finish();
    }

    /**
     * 结束指定的Activity
     */
    public static void finishActivity(Activity activity) {
        if (activity != null) {
//            activityStack.remove(activity);
            if (!activity.isFinishing()) {
                activity.finish();
            }
        }
    }


    /**
     * 结束指定的Activity
     */
    public static void finishActivity(Activity activity,boolean isRemoveStack) {
        if (activity != null) {
            if (!activity.isFinishing()) {
                activity.finish();
                if(isRemoveStack){
                    activityStack.remove(activity);
                }
            }
        }
    }

    public static void finishExcept(Class<?> cls) {
        for (Activity activity : activityStack) {
            if (!activity.getClass().equals(cls)) {
                finishActivity(activity);
            }
        }
    }

    /**
     * 结束指定类名的Activity
     */
    public static void finishActivity(Class<?> cls) {
        for (Activity activity : activityStack) {
            if (activity.getClass().equals(cls)) {
                finishActivity(activity);
            }
        }
    }

    /**
     * 结束所有Activity
     */
    public static void finishAllActivity() {
        for (Activity activity : activityStack) {
            if (activity != null) {
                activity.finish();
            }
        }
        activityStack.clear();
    }

    /**
     * 退出应用程序
     */
    @SuppressLint("MissingPermission")
    public static void AppExit(Context context) {
        try {
            finishAllActivity();
            ActivityManager manager = (ActivityManager) context
                    .getSystemService(Context.ACTIVITY_SERVICE);
            manager.killBackgroundProcesses(context.getPackageName());
            System.exit(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

添加Activity到栈 

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //添加Activity到栈
        ActivityUtil.addActivity(this);
    }
}

结束指定Activity

ActivityUtil.finishActivity(MainActivity.class);

十 两个app的通信和跳转

10.1 我们平时打开京东或者其它app,可以从应用内打开另一个应用,或者微信分享可以直接打微信的程序,还有网页H5可以跳转指定其它app页面,那这是怎样实现的呢。这就用到了应用间的跨进程跳转。

10.2 两个app,从一个app打开另一个app实现,想要打开另一个app,必须先知道app的包名,再根据包名显式和隐式的打开指定Activity。

10.3 显式方式跳转,跟正常Intent显式启动一样,指定包名和类型就可以打开

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName componentName = new ComponentName("com.dinghe.schemetest", "com.dinghe.schemetest.MainActivity");
intent.setComponent(componentName);
startActivity(intent);

10.4 网页H5跳转另一个app,通过intent-filter的data里面scheme实现。

scheme是一种页面内跳转协议,通过定义自己的scheme协议,可以非常方便跳转app中的各个页面;通过scheme协议,服务器可以定制化告诉App跳转到APP内部页面

实现步骤:

第一步:新建一个html网页test.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <!-- <a href="[scheme]://[host]/[path]?[query]">启动应用程序</a> -->
        <!--  scheme:判别启动的App -->
        <!--  host:主机                没有也可以 -->
        <!--  path:传值时必须的key      没有也可以 -->
        <!--  query:获取值的Key和Value  没有也可以 -->
        <a href="goods://test:8080/details?id=222">启动应用</a>
        <br/>
    </body>
</html>

第二步:新建目标协议页面SchemeActivity.java

public class SchemeActivity extends AppCompatActivity {
    private TextView tvContent;

    String id;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scheme);

        id=getIntent().getStringExtra("id");



        tvContent = (TextView) findViewById(R.id.tv_content);

        Intent intent = getIntent();
        Uri data = intent.getData();  //
        String action = intent.getAction();
        String scheme = intent.getScheme();
        Set<String> categories = intent.getCategories();
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("data:").append(data).append("\n\n")
                .append("action:").append(action).append("\n\n")
                .append("categories:").append(categories).append("\n\n")
                .append("scheme:").append(scheme).append("\n\n")
                .append("id:").append(data.getQueryParameterNames()).append("\n\n")
                .append("host:").append(data.getHost()).append("\n\n")
                .append("path:").append(data.getPath()).append("\n\n")
                .append("port:").append(data.getPort()).append("\n\n")
                ;


        tvContent.setText(stringBuilder);
    }
}

第三步:AndroidManifest.xml里面注册SchemeActivity的协议

<application
	android:allowBackup="true"
	android:icon="@mipmap/ic_launcher"
	android:label="@string/app_name"
	android:supportsRtl="true"
	android:theme="@style/Theme.MyApplication">
	
	<activity
		android:name=".SchemeActivity"
		android:exported="true"
		android:launchMode="singleTask">
		<intent-filter>
			<action android:name="android.intent.action.VIEW"/>
			<category android:name="android.intent.category.DEFAULT"/>
			<category android:name="android.intent.category.BROWSABLE"/>

			<data android:scheme="goods"
				android:host="test"
				android:port="8080"
				android:path="/details"
				/>

		</intent-filter>
	</activity>

</application>

第四步:跳转该协议,点击h5网页里面的启动应用按钮,就能跳转另一个app了

 

 10.6 利用三方SDK实现网页跳转其它app的方案,比如极光魔链平台运用这种短链可以实现该方案

如下流程

 创建短链

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

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

相关文章

线对象QgsLineString

几何对象中线用QgsLineString进行封装支持Z和M值&#xff0c;用于表示2维的&#xff0c;2. 5维的&#xff0c;3维的线线是由一串点连接而成 创建线 QgsLineString() #创建空的线QgsLineString(points: Iterable[QgsPoint]) #从一串QgsPoint创建QgsLineString(x: Iterable…

[JavaScript]JSON对象

eval函数 eval函数能将一个字符串当做一段JS代码解释并执行。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name&quo…

大数据经典项目案列——滴滴数据分析(云服务器-零基础从配置到项目落地1)

本次我们项目采用阿里云服务器&#xff0c;采用以下技术及框架协议&#xff0c;进行数据分析&#xff1a; HDFSHiveSpark SQLZeppelin 当然我们也可以利用数据库清洗好的数据&#xff0c;采用 1.Tableau 2.Pythonechartsweb前端 3.腾讯云、阿里云BI报表 4.当然我们也可以采…

51单片机(十四)LCD1602

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

SpringCloud Alibaba 配置中心功能

一、快速入门 1、创建工程nacos-client7777 pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&q…

基于企业网的信息安全防护系统的设计与实现_kaic

摘 要 这篇文章提供了一种新的&#xff0c;基于“禁止一切”安全策略和VxD技术的企业网络安全保障方案&#xff0c;旨在帮助企业更好地应对外界的威胁。通过设计一套完善的企业网信息安全防护系统&#xff0c;不仅可以有效地解决企业网络中存在的问题&#xff0c;而且还可以有…

一文带你了解和掌握Markdown编辑神器mdnice

无论你是博客写作爱好者&#xff0c;还是想要自己动手开发一个网站&#xff0c;你都可能会接触到Markdown。Markdown是一种轻量级的标记语言&#xff0c;它允许人们使用易读易写的纯文本格式编写文档&#xff0c;然后转换成有效的HTML内容。然而&#xff0c;当你想要将你的Mark…

MYSQL主从复制和读写分离.2

搭建MYSQL读写分离 master :192.168.142.10 slave1:192.168.142.20 slave2:192.168.142.30 Amoeba:192.168.142.40 客户端:192.168.142.50 ----Amoeba服务器配置---- ##安装 Java 环境## 因为 Amoeba 基于是 jdk1.5 开发的&#xff0c;所以官方推荐使用 jdk1.5 或 1.6 版…

Linux 指令3

文章目录 标题日期date时间戳 cal 日历find -name 查找which ls 搜指令whereisgrep 行文本过滤工具&#xff08;例如找到main函数入口&#xff09;例子 ps ajx 进程 打包压缩&#xff0c;解包解压&#xff08;过程是这么个过程&#xff0c;简化成压缩->解压&#xff09;zip多…

使用gitee上传vue项目

菜鸟教程&#xff1a;https://www.runoob.com/git/git-tutorial.html 参考文档&#xff1a;https://blog.csdn.net/handy_csdn/article/details/117400151#:~:text%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B%E6%90%AD%E5%BB%BAvue%E9%A1%B9%E7%9B%AE%EF%BC%8C%E5%B9%B6%E4%BD%BF%E7…

试用chatgpt写一篇文章,关于自动化测试框架的思路

当涉及到软件测试和自动化框架时&#xff0c;Python是一种广泛使用的编程语言。它提供了丰富的库和工具&#xff0c;使得构建测试框架变得相对容易。本文将介绍一个基于Python的自动化测试框架&#xff0c;结合了pytest、allure报告、日志记录、YAML配置、MySQL数据库以及钉钉和…

JNI 中Get<PrimitiveType>ArrayElements 和 Release<PrimitiveType>ArrayElements 函数讲解

文章目录 Get<*PrimitiveType*>ArrayElements 函数族Release<*PrimitiveType*>ArrayElements 函数族使用场景 Get<PrimitiveType>ArrayElements 函数族 函数原型&#xff1a; NativeType *Get<PrimitiveType>ArrayElements(JNIEnv *env, ArrayType ar…

vscode 标签的使用

使用标签就可以快速跳转到某一段代码,十分方便 安装 首先,我们需要安装 设置快捷键 shiftcommandp. 调出命令行 输入bookmark, 即可看到标签的相关指令 生成一个标签 设置一个你喜欢的快捷键 ,这代表 在光标所在的行上添加一个标签。需要设置一个label 调出列表 可以显示…

CMakeList.txt -- 编写保姆式教程

致每一个还坚持在互联网和软件行业的同路人。 最近有朋友问我为什么选择当程序员&#xff0c;我也不明白。可能是缺少社交能力&#xff0c;可能更喜欢心理上保存平静&#xff0c;可能是为了那份对于从无到有的沉浸感和满足感。 目录 欢迎加入陈达书--C交流群: Errrr113(非诚勿扰…

LitCTF Writeup By AheadSec

文章目录 Web我Flag呢&#xff1f;Follow me and hack mePing导弹迷踪PHP是世界上最好的语言&#xff01;&#xff01;作业管理系统Vim yyds这是什么&#xff1f;SQL &#xff01;注一下 &#xff01;就当无事发生Flag点击就送&#xff01;Http pro max plus1zjs彩蛋 Pwn只需要…

Jenkins持续集成项目搭建与实践—基于Python Selenium自动化测试

Jenkins简介 Jenkins是Java编写的非常流行的持续集成&#xff08;CI&#xff09;服务&#xff0c;起源于Hudson项目。所以Jenkins和Hudson功能相似。 在华为工作了10年的大佬出的Web自动化测试教程&#xff0c;华为现用技术教程&#xff01;_哔哩哔哩_bilibili在华为工作了10…

如何批量归类文件,按自己批定位置保存

先来给大家看下目前文件是这样的&#xff0c;一个文件夹里面保存是图片 &#xff0c;另一个文件夹保存是文档&#xff0c;我是需要一个图片对应一个文档&#xff0c;保存在同一个文件夹中。 这个是图片 这个是文档 我的需求是一张图片和一个文档保存同一个文件夹中&#xff0c…

面试篇:JVM虚拟机

一、JVM介绍&#xff0c;JVM运行流程 1、什么是JVM Java Virtual Machine&#xff1a;Java程序的运行环境 (java二进制字节码的运行环境) 好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收机制 2、JVM运行流程 二、什么是程序计数器&#x…

Rufus v4.0.2035 开源USB引导启动盘制作工具单文件版

Rufus 是一个可以帮助格式化和创建可引导USB闪存盘的工具&#xff0c;比如 USB 随身碟&#xff0c;记忆棒等等。在如下场景中会非常有用&#xff1a;你需要把一些可引导的ISO格式的镜像&#xff08;Windows&#xff0c;Linux&#xff0c;UEFI等&#xff09;创建成USB安装盘的时…

Selenium自动化测试之使用真实用户Chrome环境

Selenium每次打开Chrome浏览器时&#xff0c;每次都是一个初始的全新环境&#xff0c;有时候&#xff0c;我们需要一些当前用户的一些设置和插件等&#xff0c;便可以通过ChromeOptions参数&#xff0c;通过指定用户数据目录--user-data-dir来设置成真实用户目录来实现。 浏览…