android启动优化

2023-11-16

主题

我们今天讨论的主题是:

  • 使用第三方工具(CPU Profile)来优化app的启动时间。

背景

想要进行app的启动优化有一点必须要知道的就是Android的启动流程和启动状态。

启动流程

Android的启动流程相关的知识点,各位可以去查阅Android framework相关的资料,这里只是简单的说下启动流程。大家可以看下下面这张图。
在这里插入图片描述

  1. 点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求。
  2. system_server进程收到请求后,向zygote进程发送创建进程的请求。
  3. zygote进程fork出新的子进程,即app进程
  4. App进程,通过Binder IPC向system_server进程发起attachApplication请求。
  5. system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求。
  6. App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息。
  7. 主线程在收到Message后,通过反射机制创建目标Activity,并回调Activity.onCreate等方法。
  8. 到此,App便正式启动,开始进入activity生命周期。

因此,我们可以 整体的将应用启动分成三个阶段:

  1. 第一阶段:点击桌面Launcher应用的图标,通过与AMS(ActivityManagerService)通信,启动应用的过程。
  2. 第二阶段:应用Application执行过程。
  3. 第三阶段:启动Activitv执行过程过程。
启动状态

应用有三种启动状态,每种状态都会影响应用向用户显示所需的时间:冷启动、温启动与热启动。
在冷启动中,应用从头开始启动。在另外两种状态中,系统需要将后台运行的应用带入前台。建议始终在假定冷启动的基础上进行优化。这样做也可以提升温启动和热启动的性能。

  • 冷启动——冷启动是指应用从头开始启动:系统进程在冷启动后才创建应用进程。发生冷启动的情况包括应用
    自设备启动后或系统终止应用后首次启动。
  • 热启动——在热启动中,系统的所有工作就是将 Activity 带到前台。只要应用的所有 Activity 仍驻留在内存中,应用就不必重复执行对象初始化、布局加载和绘制。
  • 温启动——包含了在冷启动期间发生的部分操作;同时,它的开销要比热启动高。有许多潜在状态可视为温启动。
    例如:用户在退出应用后又重新启动应用。进程可能末被销毁,继续运行,但应用需要执行oncreate()从头开始重新创建 Activity。
    系统将应用从内存中释放,然后用户又重新启动它。进程和 Activity 需要重启,但传递到oncreate()的已保存的实例state bundle 对于完成此任务有一定助益。

疑问

我们该如何衡量启动时间呢?或者说如何证明启动速度变快了呢?

  • 冷启动统计耗时
    在性能测试中存在启动时间2-5-8原则:
  1. 当用户能够在2秒以内得到响应时,会感觉系统的响应很快;
  2. 当用户在2-5秒之间得到响应时,会感觉系统的响应速度还可以;
  3. 当用户在5-8秒以内得到响应时,会感觉系统的响应速度很慢,但是还可以接受;
  4. 而当用户在超过8秒后仍然无法得到响应时,会感觉系统糟透了,或者认为系统已经失去响应。

Google 也提出一项计划:Android Vitals。该计划旨在改善 Android 设备的稳定性和性能。当选择启用了该计划的用户运行您的应用时,其 Android 设备会记录各种指标,包括应用稳定性、应用启动时间、电池使用情况、呈现时问和权限遭拒等方面的数据。Google Play 管理中心 会汇总这些数据,并将其显示在 Android Vitals 信息中心内。
当应用启动时间过长时,Android vitals 可以通过 Play 管理中心提醒您,从而帮助提升应用性能。Android Vitals在您的应用出现以下情况时将其启动时间视为过长:

  • 冷启动用了5秒或更长时间。
  • 温启动用了 2秒或更长时间。
  • 热启动用了 1.5 秒或更长时间。

注意:这些时间其实只是一个参考值,并不是一个标准,不能说某台设备冷启动时间超过5s就认为启动时间过长了。因为app的启动时间跟设备有着很大的关系,如果一台性能很差的设备来运行app,可能它就是需要这么长的时间。
实际上不同的应用因为启动时需要初始化的数据不同,启动时间自然也会不同。相同的应用也会因为在不同的设备,因为设备性能影响启动速度不同。所以实际上启动时间并没有绝对统一的标准,我们之所以需要进行启动耗时的统计的,可能在于产品对我们应用启动时间提出具体的要求。

耗时统计的两种手段:系统日志统计和adb命令统计。

系统日志统计

在Android 4.4(AP1 级别 19)及更高版本中,logcat 包含一个输出行,其中包含名为 Displayed 的值。此值代表从启动进程到在屏幕上完成对应 Activity 的绘制所用的时间。

ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms

如果我们使用异步懒加载的方式来提升程序画面的显示速度;这通常会导致的一个问题是,程序画面已经显示,同时 Displayed 日志已经打印,可是内容却还在加载中。为了衡量这些异步加载资源所耗费的时间,我们可以在异步加载完毕之后调用 activity.reportFul1yDrawn()方法来让系统打印到调用此方法为止的启动耗时。

adb命令统计

查看启动时间的另一种方式是使用命令:

adb shell am start -S -W com.example.app/.MainActivity
-c android.intent.category.LAUNCHER//可以不加这句
-a android.intent.action.MAIN//可以不加这句

启动完成后,将输出:

ThisTime:415
TotalTime:415
WaitTime:437

  • WaitTime:总的耗时,包括前一个应用Activity pause的时间和新应用启动的时间;
  • ThisTime:表示一连串启动Activity的最后一个Activity的启动耗时;
  • TotalTime:表示新应用启动的耗时,包括新进程的启动和Activity的启动,但不包括前一个应用Activity pause的耗时。
    开发者一般只要关心TotalTime即可,这个时间才是自己应用真正启动的耗时。

优化方向

上面我们说到app的启动流程可以分为3个阶段。

  • 关于第一阶段的优化方向,这个需要framework工程师来实现的,如果是app开发程序员基本上是无能为力的。

  • 关于第二阶段的优化方向,我们首先需要了解下application执行阶段会做些什么事情?首先会初始化构造方法,然后会执行他的第一个函数attachBaseContext方法, 接着还有会执行它的oncreate回调方法。
    在Application 执行这两个方法的时候,我们的app程序都在显示什么?显示的是一个黑白屏(究竟是黑屏还是白屏这就要看我们应用设置的theme),这个黑白屏要持续多长时间?这个时间就是我们要启动优化的时间。
    在实际开发中,我们往往会讲这个黑白屏进行设置,设置为一个需要显示的图片,或者广告图片,这个图片的显示会使用户产生错觉:以为进入了app。然而,app其实并没有任何的优化。
    因此,针对这个阶段的优化主要有三个部分:第一部分是attachBaseContext回调方法的优化,第二部分是onCreate
    回调方法的优化,第三部分就是对应用执行到Activity之前的白屏处理(注意如果是对application所使用的theme的android:windowBackground进行设置要在显示activity的设置会原来的形式,因为android:windowBackground是影响整个app的,即该app的所有页面都共用同一个windowBackground)。
    这里,说下windowBackground这个属性的作用。我们知道一个app有一个window,因此如果这个属性被改动了,那么整个app的背景都会受影响。通常我们app的背景颜色是白色或者黑色就是与这个属性有密切的关系。假设一种情况,如果我们将该属性设置为透明,在我们的布局文件不设置backgroundColor的情况下,大家猜猜会是怎么样的一个效果。没错,你将会看到app的背景是手机的桌面。

  • 关于第三阶段的优化方向,在这个阶段,主要是第一个activity 运行的阶段,直到activity执行完成onResume函数之后,这个启动过程才算是完
    成了,因此,第一个activity启动过程中的 onCreate()函数,onStart()函数,onResume()函数都将是我们需要优化的点。不能在这几个函数里面进行耗时的工作。
    onCreate()函数的优化
    一般这个函数里面做的事情是setContentView (resld);这个函数相对耗时,这个函数的执行其实是反射,用反射去解析xml,这个过程自然是耗时的。
    另外,大家一定要尽可能的使用 约束布局来改造相对布局和线性布局,这个过程可以达到減少布局层级的效果,Google有分析,constraintlayout 会比RelativeLayout的效率要高40%。
    onStart()、onResume()函数优化
    为了快速加载Activity所需的数据,可以采用缓存的方式。如果数据异步加载成功后,会更新缓存。启动初始化时,可能会有很多接口,这里最好在启动时只通过一个接口拉取应用启动和MainActivity的主Fragment展示的所有数据。需要显示多少,就加载多少数据,不要额外的加载数据。此时,懒加载是一个非常好的选择。
    另外,IdleHandler 是 MessageQueue 内定义的一个接口,一般可用于做性能优化。当消息队列内没有需要立即执行的 message 时,会主动触发 IdleHandler 的 queueIdle 方法。返回值为 false,即只会执行一次;返回值为 true,即每次当消息队列内没有需要立即执行的消息时,都会触发该方法。

Looper.myQueue().addIdleHandler(new IdleHandle() {
	@override
	public boolean queueIdled{
	//你想做的任何事情
	//...
	return false;
}}):

android中主线程要处理的所有的事务全部都是在handler里面完成的,小到每一个按键事件,大到每一个activity 的生命周期,都是主线程handler中的一个Message。那么每一个Message都是存储在—MessageQueue里面,当我们messagequeue里面没有消息要立刻执行的时候,说明主线程
没有任务要做,这个就是主线程的空档,于是,我们就可以利用这个空档去做耗时任务。这个时候我们开发者就可以利用这一点,来把耗时任务放到这个idleHandler里面执行,从而提升了运行的速度。注意:不能够太耗时哦,因为本质上也是通过handler发送消息的,如果太耗时会导致后面的事件无法及时响应。

接下来,进入我们的重头戏:使用CPU Profile来优化启动速度。
请注意:开启这个功能可能会导致电脑卡顿,app打开时间要比一般情况下长。
在这里插入图片描述
Sample Java Methods
对Java 方法采样:在应用的Java 代码执行期间,频繁捕获应用的调用堆栈。分析器会比较捕获的数据集,以推导与应用的Java 代码执行有关的时间和资源使用信息。如果应用在捕获调用堆栈后进入一个方法并在下次捕获前退出该方法,分析器将不会记录该方法调用。如果您想要跟踪生命周期如此短的方法,应使用检测跟踪。
Trace Java Methods
跟踪Java 方法:在运行时检测应用,以在每个方法调用开始和结束时记录一个时间戳。系统会收集并比较这些时间戳,以生成方法跟踪数据,包括时间信息和 CPU 使用率。
Sample C/C++ Functions
对C/C++方法采样:捕获应用的原生线程的采样跟踪数据。要使用此配置,您必须将应用部署到搭载Android 8.0 (API 级别 26) 或更高版本的设备上。
Trace System Calls
跟踪系统调用:捕获非常详细的细节,以便您检查应用与系统资源的交互情况。您可以检查线程状态的确切时间和持续时间、直观地查看所有内校的 CPU 瓶颈在何处,并添加要分析的自定义跟踪事件。要使用此配
置,您心须将应用部署到搭载 Android 7.0 (API级别 24) 或更高版本的设备上。
此跟踪配置在 systrace 的基础上构建而成。您可以使用 systrace 命令行实用程序指定除 CPU Profiler 提供的选项之外的其他选项。systrace 提供的其他系统级数据可帮助您检查原生系统进程并排查丢帧或帧延迟问题。

如果我们只是进行app启动方面的优化,一般选择第2个即可。
下面,我们以一个案例来演示下如何使用这个工具。

  • 首先使用adb命令看下我们优化之前的耗时:
    在这里插入图片描述
    通过totalTime,我们可以看到冷启动所耗时的时间4s多。

  • 其次,我们点击Profile按钮,等待页面展示出来之后,再点击stop按钮即可。稍等一下会生成一份文件
    在这里插入图片描述
    在这里插入图片描述
    我们选择“Top Down”,然后定位到耗时多的地方,之后找到我们自己写的代码。因为例子中我在activity的oncreate方法中休眠了4s,因此当我们删除这段休眠代码时,再看下耗时时间。
    在这里插入图片描述
    耗时从之前4s多减少到了900多ms。

  • 最后我们再使用adb命令看下我们优化之后的耗时:
    在这里插入图片描述
    除了可以使用Profile启动外,我们还可以使用DebugAPI生存trace文件,然后将trace文件拖入as的编辑窗口中,同样可以得到一份和Profile相似的报告。

public class MyApplication extends Application {
	public MyApplication(){
		Debug. startMethodTracing("brett");
	}
}
public class MainActivity extends AppCompatActivity {
	@Override
	public void onWindowFocusChanged (boolean hasFocus) {
		super.onWindowFocusChanged(hasFocus);
		Debug. stopMethodTracing();
	}
}

运行App,则会在sdcard中生成一个brett.trace文件(需要sdcard读写权限)。将手机中的trace文件保存至电脑,随后拖入Android studio即可。因为Profile是需要Android8以上的手机才可以使用的,针对与android8以下系统的手机我们可以使用这种方式。

补充:严苛模式

StrictMode是一个开发人员工具,它可以检测出我们可能无意中做的事情,并将它们提请我们注意,以便我们能够修复它们。
StrictMode最常用于捕获应用程序主线程上的意外磁盘或网络访问。帮助我们让磁盘和网络操作远离主线程,可以使应用程序更加平滑、响应更快。一般建议在debug中开启。

public class MyApplication extends Application
@Override
public void onCreate(){
	if (BuildConfig.DEBUG) {
	//线程检测策略
StrictMode.setThreadPolicy(newStrictMode.ThreadPolicy.Builder()
	.detectDiskReads()
	//读、写操作
	.detectDiskWrites()
	.detectNetwork()
	// or .detectAll() for all detectable problemspenaltyLog()build());
	StrictMode.setVmPolicy(newStrictMode.VmPolicy.Builder()
		.detectLeakedSqlLiteObjects()	//Sqlite对象泄露
		.detectLeakedClosableobjects() //末关闭的C1osable对象泄露
		.penaltyLog() //违规打印日志
		.penaltyDeath() //违规崩溃
		.build());
	}
}

最后

启动速度优化也会涉及到布局优化与卡顿优化,包括内存抖动等问题。优化是一条持续的道路,很多时候我们会发现通过各种检测手段花费了大量的精力去对代码进行修改得到的优化效果可能并不理想。因为优化就是一点一滴积累下来的,我们平时在编码的过程中就需要多注意自己的代码性能。
可能实际过程中优化并不会很顺利,不同的设备上可能表现不一样。我们只能结合对业务、对自己代码的了解去不断去实践。

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

android启动优化 的相关文章

  • 从队列更新活动的最佳方法

    我有一个LinkedBlockingQueue在我的 生产者 调解者 消费者 模型中的调解者中 Producer 首先更新将 Mediator 添加到 ActivityQueue 中 接下来 消费者 活动在队列中等待 侦听并获取下一个项目
  • 有关 paddingStart 使用的冲突 lint 消息

    API 17 RTL 支持发布后 我将以下内容添加到我的清单中 android supportsRtl true 这导致 Lint 在我的视图中有 paddingLeft Right 的地方正确地向我发出这些警告 考虑添加 android
  • RecyclerView 未显示列表中的所有项目

    我在用RecyclerView在我的应用程序中 每次我打开屏幕时 我只能看到一项 但当我调试时 它每次都会出现onBindViewHolder method 这是我的适配器 Override public ViewHolder onCrea
  • PHP服务器端IAB验证openssl_verify总是返回0

    我使用以下函数 服务器端 php 来验证 IAB v3 事务 我从 Android 应用程序传递过来 Override protected void onActivityResult int requestCode int resultCo
  • Mesibo 通话 UI 未更新

    我正在尝试更改 Mesibo Call UI 的配置 但它并没有改变 我尝试如下 MesiboCallConfig mesiboCallConfig new MesiboCallConfig mesiboCallConfig backgro
  • Android Accessibility 执行触摸操作

    我想知道是否可以使用 Android 辅助功能服务在屏幕上的位置执行触摸操作 例如 Bundle arguments new Bundle arguments putInt coord X X value arguments putInt
  • 无论如何,要控制宋何时选择Android.bp,何时不选择?

    使用新的构建系统 即 Soong 安卓取代Android mk with Android bp 还有 Android Q 及以上版本 Soong将选择所有Android bp文件 无论所有文件都存在于何处 早些时候 对于 2 级和 3 级模
  • 无法从 com.android.aaptcompiler.ParsedResource@ef79973 提取资源

    无法从 com android aaptcompiler ParsedResource ef79973 提取资源 无法从 com android aaptcompiler ParsedResource 4c95ce87 提取资源 C Use
  • Flutter Spotify Api 身份验证

    我需要在使用 Spotify api 的 Flutter 应用程序中对用户进行身份验证 我使用 flutter web auth 打开 WebView 并让用户在那里登录 我无法返回应用程序 在 Spotify 仪表板中 我将回调 Uri
  • 如何在虚拟机 VirtualBox 上运行 Android-x86 4.2 iso?

    我想用Android x86测试和调试我的应用程序 我之前成功尝试过其他版本的Android x86 但是关于android x86 4 2有一个错误 所以我在这里问我的问题 因为它可能会发生在其他人身上 我安装了oracle VM vir
  • Android - 正确使用 invalidateOptionsMenu()

    我一直在寻找很多invalidateOptionsMenu 我知道它的作用 但我想不出这种方法在现实生活中有用的任何例子 我的意思是 例如 假设我们要添加一个新的MenuItem to our ActionBar 我们可以简单地获取菜单on
  • 使用 Glide 库设置图像加载完成后进度条的可见性

    您好 我想要一个图像进度条 该进度条将在图像加载时显示 但当图像加载完成时 我想将其设置为消失 早些时候我为此使用了毕加索库 但我不知道如何将它与 Glide 库一起使用 我知道有一些资源就绪功能 但我不知道如何使用它 谁能帮我 毕加索图书
  • InAppMessage 一旦显示就会自动消失

    您好 我最近将 InAppMessaging 添加到我的项目中 这似乎很容易集成 但对我来说并没有按预期工作 首先 我将其添加到 build gradle 中 implementation com google firebase fireb
  • 为什么 ExpandableListView 更改 ChildView 设置(Android)?

    我对使用 ExpandableListView 有疑问 就我而言 我有两个组视图和两个子视图 而子视图由一个带有多个按钮 文本视图等的相对布局组成 例如 当首先扩展第二组并对视图持有者进行一些更改并随后扩展第一组时 先前所做的更改也会自动应
  • BadPaddingException:无效的密文

    我需要一些帮助 因为这是我第一次编写加密代码 加密代码似乎工作正常 但解密会引发错误 我得到的错误是 de flexiprovider api exceptions BadPaddingException 无效的密文 in the 解密函数
  • 获取当前图片在图库中显示的位置

    在我的应用程序中 我有一个图片库 但我想检测当前显示图像的位置 例如 当我启动我的活动时 位置是 0 但是当我在图库中滚动时 我想获取当前显示图像的位置 我尝试过 OnFocusChanged OnItemClicked 但只有当我单击图库
  • 如何以编程方式创建 CardView

    我正在开发一个 Android 应用程序Java Android Studio 我想在活动中创建CardView以编程方式 我想将以下属性设置为CardView layout width wrap content layout row 0
  • Android:如何在布局中放置纯色矩形?

    我有一个可以很好地膨胀的relativelayout 我想在顶部添加一个跨越布局宽度的纯色矩形 我尝试将以下内容放入我的 xml 中
  • compileReleaseKotlin 失败并出现 java.lang.ClassNotFoundException:com.sun.tools.javac.util.Context

    我正在尝试使用 gradlew 通过终端构建我的 Android 项目 其中包含库模块 在 Android Studio 中 它编译并安装成功 但是当我尝试运行时 gradlew assembleDebug我得到以下堆栈跟踪 Using k
  • 如何让用户在android列表视图中选择主题?

    我有一个带有两个标签的列表视图 标题和副标题 我想要深色和浅色背景作为用户选项 标题具有 textAppearanceMedium 副标题具有 textAppearanceSmall 我希望样式 MyTheme Dark 具有白色文本 My

随机推荐

  • 远程连接MySQL报错ERROR 2003解决办法

    转自 http www 111cn net database mysql 48040 htm 问题代码代码 ERROR 2003 HY000 Can t connect to MySQL server on 192 168 0 19 111
  • C++继承详解

    文章目录 前言 一 继承的概念和定义 1 继承的概念 2 继承的定义 二 继承方式和访问限定符 三 基类和派生类对象赋值转换 四 继承中的作用域 五 派生类的默认成员函数规则 六 菱形继承 七 继承小总结 前言 在现实生活中我们会遇到不同身
  • 单向散列函数(Hash)

    http www cnblogs com happyhippy archive 2006 12 23 601368 html 单向散列函数 Hash 0 Hash函数的性质 常用Hash函数 MD5 128bit SHA 1 160bit
  • Windows系统输入法的相关文件

    以下是Windows ime目录下自带的输入法的相关文件列表 全拼 Winpy ime Winpy mb Winpy hlp Winpy cnt 双拼 Winsp ime Winsp mb Winsp hlp Winsp cnt 微拼 Pi
  • 云计算中的海量数据存储在哪_云计算中的块级数据存储如何工作

    云计算中的海量数据存储在哪 Cloud computing and IT demands are directly proportional to each other To deliver consistency with securit
  • MySQL-分库分表详解(二)

    作者 小刘在C站 个人主页 小刘主页 努力不一定有回报 但一定会有收获加油 一起努力 共赴美好人生 学习两年总结出的运维经验 以及思科模拟器全套网络实验教程 专栏 云计算技术 小刘私信可以随便问 只要会绝不吝啬 感谢CSDN让你我相遇 前言
  • WSL2 安装 Arch Linux 子系统

    WSL 介绍与安装 Windows Subsystem for Linux 以下简称为 WSL 允许开发人员直接在Windows上运行GNU Linux环境 包括大多数命令行工具 实用程序和应用程序 无需修改 无需传统虚拟机或双引导设置的开
  • 数据结构和算法(堆排序和哈夫曼树、哈夫曼编码、解码)

    堆排序 一般使用大顶堆升序排列 使用小顶堆降序排列 下图为代码测试的树 数组格式 堆降序代码实现 import java util Arrays public class HeapSort public static void main S
  • 移植应用Wireless Tools

    移植应用Wireless Tools 前提条件 下载源码 打个补丁 解压缩源码 打补丁 编译安装 使用方法 大致流程 常见问题 前提条件 下载源码 点击前往下载 或者使用以下命令 wget c https hewlettpackard gi
  • Unity2019.4.31f1 物体动画切换与移动

    控制小鸡每隔一定时间就随机执行一个动作 该动作在三个动作中随机选择 摆头 吃东西 行走 其中行走会随机选择一个方向 进行旋转并前进一段时间 ChickenController cs using System Collections usin
  • 异常之自定义异常类

    自定义的异常类一般步骤 1 自定义异常类要继承于Exception类或其子类 或其它异常类 2 为自定义异常类声明字段 属性 成员 方法成员或重写父类的字段和方法 3 自定义异常类至少要定义两个构造方法 一个是无参的 另外一个是带 Stri
  • python操作word——python-docx和python-docx-template模块

    前言 项目用到了导出文档 综合考虑使用python docx模块 目录 python docx 安装 docx文档布局词汇 三个部分 文档 段落 文字块 四级结构 表格 使用 导入word 读操作 获取段落 获取段落文本内容 获取文字块文本
  • AD铺铜中铺地选择异形铺铜方式

    在使用AD时 最后的一步铺铜 铺地 如果是矩形的板子 铺铜很简单 直接捕捉拐角点即可 但是一些异形的板子 就不是那么好办了 虽然可以全选铺铜 最后也不影响最后的PCBA实物 但是有强迫症的肯定会看着不舒服 比如我 所以找到一种快速铺异形板子
  • Go(一)变量和常量

    目录 标识符与关键字 标识符 关键字 变量 变量的来历 变量类型 变量声明 标准声明 批量声明 变量的初始化 类型推导 短变量声明 匿名变量 常量 iota 几个常见的iota示例 标识符与关键字 标识符 在编程语言中标识符就是程序员定义的
  • Spark数据处理实战之列空值&新增列处理

    在spark dataset dataframe操作过程中 我们经常会遇到对于一个列值的一些判断情况 是否为NULL 创建一个新列等 本文讲解了常用的增加列的方法 并且对于列空值判断 填充处理以及查询的api做了详细的描述和实例讲解 阅读完
  • 思科交换机密码破解

    年纪大了 总是忘记cisco交换机密码 现将我初始化cisco交换机密码的两大步13个小步骤记录如下 A 1 打开电脑中SecureCRT软件 或者下载windows7 超级终端 v1 01 绿色版 hypertrm exe 把port C
  • 人人都看得懂的正则表达式教程

    编写验证规则最流行和最简单的方法就是正则表达式了 但唯一的一个问题是正则表达式的语法太隐晦了 让人蛋疼无比 很多开发者为了在项目中应用复杂的验证 经常要使用一些小抄来记住正则式的复杂语法和各种常用命令 在这篇文章中 我将试图让大家明白什么是
  • uboot 设置环境变量

    1 使用命令 ipconfig 查看 windows 系统的 IP 2 使用命令 ifconfig 查看虚拟机 ubuntu 系统的 IP 3 串口登录 fs4412 的uboot 4 在uboot中输入命令 print 打印当前环境变量
  • 如何将栈中的元素输出

    首先需要写一个出栈函数 得到栈顶的值 才能将其输出 bool Pop SqStack s ElemType e if s gt top 1 return false e s gt data s gt top s gt top return
  • android启动优化

    主题 我们今天讨论的主题是 使用第三方工具 CPU Profile 来优化app的启动时间 背景 想要进行app的启动优化有一点必须要知道的就是Android的启动流程和启动状态 启动流程 Android的启动流程相关的知识点 各位可以去查