面试总结Androidservice两种启动模式的区别Service有两种启动方式,分别是startService和

Service有两种启动方式,分别是startService和binderService。

Service默认运行在UI线程中,所以里面不能做耗时操作,要做耗时操作就必须开启一个子线程操作。

IntenService其实是继承自Service,只不过内部默认开启了一个子线程处理所有的Intent请求。

而多次调用startService只会执行onStartCommand方法,但是启动线程的动作友只在onCreate中,所以并不会再次启动新的线程,每次执行onStartService时会通过Message的sendMessage发送一条消息到消息队列中。也就是说通过唯一的一个子线程来处理各个请求,并按照Looper的队列顺序一个接一个执行。

我们都知道,我们自定义View的时候需要实现三个方法,分别是:onMeasure(测量)、onLayout(布局)、onDraw(绘制)。

此时我们会想到一个问题:View到底是如何测量的,如何布局的,最终是如何绘制到界面上的?

我们需要从底层知道自定义View的时候是如何触发这三个函数的以及是如何管理的,由谁来管理的。

我们知道,我们所有的界面显示都是在Activity上进行的,每个Activity都对应一个窗口Window,这个窗口在Android里就是PhoneWindow

当我们调整imageview的大小时,Picasso会不管imageview大小是什么,总是直接缓存整张图片,而Glide就不一样了,它会为每个不同尺寸的Imageview缓存一张图片,也就是说不管你的这张图片有没有加载过,只要imageview的尺寸不一样,那么Glide就会重新加载一次,这时候,它会在加载的imageview之前从网络上重新下载,然后再缓存。

举个例子,如果一个页面的imageview是300*300像素,而另一个页面中的imageview是100*100像素,这时候想要让两个imageview像是同一张图片,那么Glide需要下载两次图片,并且缓存两张图片。

因为Glide在加载资源的时候,如果是在Activity、Fragment这一类有生命周期的组件上进行的话,会创建一个透明的RequestManagerFragment加入到FragmentManager之中,感知生命周期,当Activity、Fragment等组件进入不可见,或者已经销毁的时候,Glide会停止加载资源。

但是如果,是在非生命周期的组件上进行时,会采用Application的生命周期贯穿整个应用,所以applicationManager只有在应用程序关闭的时候终止加载。

主要是通过RequestManager类和Lifecycle接口来实现的。

通过这种机制,Glide能够感知到关联组件的生命周期变化,并根据生命周期的状态来启动、暂停或取消对应的图片加载请求,从而确保了图片加载操作与组件生命周期的同步,避免了潜在的内存泄漏和资源浪费问题。

Glide感知生命周期的主要目的是确保在图片加载过程中,及时地根据组件的生命周期状态进行加载操作的开始和取消,以提高应用的性能和用户体验,具体目的包括:

综上所述,Glide感知生命周期的目的是为了提高应用的性能和用户体验,确保在图片加载过程中,能够及时地根据组件的生命周期状态进行加载操作的开始和取消,从而避免不必要的资源消耗和性能问题。

Handler很重要,它和Binder进程间通信可以说是组成Android最重要的两部分。为什么说Hanlder很重要,我觉着主要有以下三个方面:

其中MessageQueue被Looper管理,Looper在构造时同步会创建MessageQueue,并利用ThreadLocal这种TLS,将其与当前线程绑定。而App的主线程在启动时,已经构造并准备好主线程的Looper对象,开发者只需要直接使用即可。

IdleHandler说白了,就是Handler机制提供的一种,可以在Looper事件循环的过程中,当出现空闲的时候,允许我们执行任务的一种机制。

IdleHandler被定义在MessageQueue中,它是一个接口。

//MessageQueue.javapublicstaticinterfaceIdleHandler{booleanqueueIdle();}既然IdleHandler主要是在MessageQueue出现空闲的时候被执行,那么何时出现空闲?

Q:IdleHandler有什么用?

Q:MessageQueue提供了add/removeIdleHandler的方法,是否需要成对使用?

Q:当mIdleHanders一直不为空时,为什么不会进入死循环?

Q:是否可以将一些不重要的启动服务,搬移到IdleHandler中去处理?

Q:IdleHandler的queueIdle()运行在那个线程?

Retrofit并不是网络请求框架,严格说只是对网络请求的一种封装,我们只需要定义一个接口类,在请求方法上加上相应的注解,甚至都不需要实现,就可以实现网络请求

Retrofit最重要的就是内部的动态代理模式

静态代理:Java中的静态代理要求代理类(ProxySubject)和委托类(RealSubject)都实现同一个接口(Subject)。静态代理中代理类在编译期就已经确定,而动态代理则是JVM运行时动态生成,但是静态代理代码冗余大,一旦需要修改接口,代理类和委托类都需要修改。这也是静态代理的缺陷。

举个例子:假如我有一套房子需要出售,我(真实对象)需要将房子委托给中介公司(代理对象),中介来帮助我出售房子(抽象对象)

动态代理:-JDK自带的java.lang.reflect.Proxy,只能代理接口类我们的类一般由Java源文件编译出Java字节码.class文件,然后经过类加载器ClassLoader加载使用。

我们知道Rxjava是一种链式调用的方式实现我们的一次网络请求

Observable.create(...)//在io调度器上执行.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(...)//在Android主线程上执行Rxjava通过subscribeOn实现切换到工作线程,创建一个ObservableObserveOn对象。会执行subscribeActual方法

如果在使用Handler时,未正确处理消息队列和对外部类弱引用,可能导致外部类无法被回收。

在Android开发中,Context引用是非常常见的内存泄漏原因。当将一个长生命周期的对象与Context关联时,如果未正确解除引用,将导致Context无法被回收。

关于LeakCanary的原理,官网上已经给出了详细的解释。翻译过来就是:

ANR:全称:applicationnoresponse(应用程序无响应),Android设计ANR的用意主要是系统通过与之交互的组件,比如Activity,Service以及用户的操作(触摸、滑动、点击)对它们进行监控,用于判断我们的应用进程是不是存在卡死或者是响应过慢的一个状态,这其实是很多应用当中一种WatchDog(看门狗)的一种设计,当我们的应用程序发生了ANR的时候,我们的应用程序会为我们采集内存、CPU等一些信息,同时会在我们的/Data/ANR目录下生成对应的Trace文件。而我们要去分析ANR的原因以及解决问题,那我们就需要结合这个Trace文件,分析Trace文件来分析原因。

我们在开发过程中出现了各种各样的问题,我们可以通过异常信息或者日志快速区跟踪问题发生的原因,但是当我们的应用上线后,这些问题就很难监控了,那我们的应用程序线上发生ANR时,我们要如何监控呢?我们可以监听我们Trace文件的改变(Android6.0之前),6.0以后我们业界有两种方式监听ANR。

第二种就是通过信号机制来监听的,信号机制类似于Android的广播,当我们在ANR发生的时候,我们的操作系统会给我们发生一个信号。我们Android系统在接到底层发出这个信号时,就会判断发生了ANR,去采集ANR的信息,那我们也可以通过这种方式来监控,爱奇艺的性能监控工具(xCrash)就是通过这种方式实现的。这块主要是通过C/C++的代码,去进行信号的注册,当我们的ANR的信号发生时,就会执行我们注册的函数,用来监控。

是指从手指接触屏幕至手指离开屏幕这个过程产生的一系列事件。一般情况下,事件列都是以DOWN事件开始、UP事件结束,中间有无数个MOVE事件。

将点击事件(MotionEvent)传递到某一个具体的View处理的全过程。

即事件传递的过程=事件分发过程

Activity、ViewGroup、View。Android的UI界面由Activity、ViewGroup、View及其派生类组成

即:1个点击事件发生后,事件先传到`Activity`、再传到`ViewGroup`、最终到`View`4.事件分发过程由哪些方法协作完成?

由三种方式协作完成:dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()

Android事件分发流程=Activity->ViewGroup->View

即:1个点击事件发生后,事件先传到Activity、再传到ViewGroup、最终到View

即要想充分理解Android分发机制,本质上是要理解:

流程1。Activity对点击事件的分发机制;当一个点击事件发生时,从Activity的事件分发开始(Activity.dispatchTouchEvent()),流程总结如下:

核心方法:dispatchTouchEvent和onTouchEvent总结如下:

流程2。ViewGroup的事件分发机制

从上面Activity的事件分发机制可知,在Activity.dipatchTouchEvent()实现了将事件从Activity->ViewGroup的传递,ViewGroup的事件分发机制从dispatchTouchEvent()开始。

核心方法:dispatchTouchEvent()、onTouchEvent()、onInterceptTouchEvent()总结如下:

流程3。View的事件分发机制

从上面ViewGroup事件分发机制知道,View的事件分发机制从dispatchTouchEvent()开始。流程总结如下:

这里需要特别注意的是,onTouch()的执行先于onClick()

核心方法:dispatchTouchEvent()、onTouchEvent()总结如下:

Android事件分发工作流程-总结

Android事件分发流程=Activity->ViewGroup->View,即:1个点击事件发生后,事件先传到Activity、再传到ViewGroup、最终再传到View。

内存过小解决办法:

内存泄漏如何分析?

在Android开发中,内存泄漏是一个常见问题,可能会导致应用程序性能下降,甚至在严重情况下导致应用程序崩溃。以下是一些解决Android内存泄漏问题的步骤:

LeakCanary是一个用于检测Android和Java应用程序内存泄漏的工具。它是由Square公司开发的,是一个开源库,可以帮助开发者在开发测试阶段更容易地发现内存泄漏的情况。

LeakCanary的工作原理是在不影响程序正常运行的情况下,动态收集程序存在的内存泄漏问题。它会在Activity的onDestroy方法执行时,对Activity创建一个带ReferenceQueue的弱引用,并检查这个引用是否被清除。如果没有被清除,就认为存在内存泄漏,然后通过另一个进程分析内存泄漏的信息并展示出来。

使用LeakCanary可以极大地方便Android应用程序的开发,因为开发者不需要每次在开发流程中都抽出专人来进行内存泄漏问题检测。将LeakCanary集成到自己的程序中也非常简单,只需要引入LeakCanary提供的jar包即可。一旦检测到内存泄漏,LeakCanary就会dump内存信息,并通过另一个进程分析内存泄漏的信息并展示出来。

Android开发中卡顿问题一直是个比较棘手又重要的问题,严重影响用户体验;卡顿是人的一种视觉感受,比如我们滑动界面时,如果滑动不流畅我们就会有卡顿的感觉,这种感觉我们需要有一个量化指标,在编程时如果开发的程序超过了这个指标我们认为其是卡顿的

过度绘制会导致界面消耗性能,严重还会出现卡顿

我们在写RecyclerView的时候,如果RecyclerView的父布局、RecyclerView、item三者的背景只要其中一个设置就可以了,没有设置背景就不会渲染,否则就会有过度绘制的情况

●父布局套子布局也是尽量只设置其中一个背景,除非没办法都需要背景

●子view一般绘制后是会覆盖父view,所以一般选择把背景设置在子view

●视图的层级结构能减少就减少,层级越多绘制速度越慢

●尽量少设置view的透明度,如果一个view设置了alpha,那他需要知道下面的view是什么内容,再绘制自己,就是过度绘制。如果是文字有透明度,可以在色号里就设置好

移除没用的布局和控件,假设添加个背景,尽可能在已经布局上放,减少只有背景功能的控件

●减少透明度的使用,假设:#55FFFFFF和#888888颜色类似,建议使用后者,因为前者有Alpha,view需要至少绘制两次

●去掉多余的不可见颜色背景、图片等,只保留最上层用户可见即可

●减少布局层次结构,避免多层嵌套约束布局ConstraintLayout等父类布局

●基本控件LinearLayout性能比RelativeLayout高一些,要提前根据UI想好哪个布局更合适,要有的方式,对症下药

●自定义View尽可能只更新渲染局部区域,杜绝不断全部重绘

●推荐使用IDE自带的Lint或者阿里代码检查插件,对于标黄警告等提示重视起来,能改的就改

●使用AndroidStudio自带的LayoutInspector层级检测工具,可以立体的查看界面的层级布局。

MVP的特点

MVP的优点

MVP的缺点

上面例子只是由于简单的主线程耗时操作造成的ANR,造成ANR的原因还有很多:

解决办法:避免死锁的出现,使用子线程来处理耗时操作或阻塞任务。尽量避免在主线程queryprovider、不要滥用SharePreferences

解决办法:文件读写或数据库操作放在子线程异步操作。

解决办法:AndroidManifest.xml文件中可以设置android:largeHeap="true",以此增大App使用内存。不过不建议使用此法,从根本上防止内存泄漏,优化内存使用才是正道。

从桌面点击一个图标后,到界面显示,这个过程发生了什么?

①点击桌面App图标,Launcher进程采用BinderIPC向system_server进程发起startActivity请求;

②system_server进程接收到请求后,向zygote进程发送创建进程的请求;

③Zygote进程fork出新的子进程,即App进程;

④App进程,通过BinderIPC向sytem_server进程发起attachApplication请求;

⑤system_server进程在收到请求后,进行一系列准备工作后,再通过binderIPC向App进程发送scheduleLaunchActivity请求;

⑥App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;

⑦主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。

⑧到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面。

Android应用启动方式主要有两种,冷启动和热启动。

Activity的启动模式,也就是常见的四种启动模式

1.standard

android.util.AndroidRuntimeException:CallingstartActivity``from``outsideofanActivitycontextrequirestheFLAG_ACTIVITY_NEW_TASKflag.Is``this``reallywhatyouwant上面错误的原因是被启动的Activity是标准模式,而发起启动请求的Context不是Activity的Context,而是系统的Context,所以系统的Context需要设置FLAG_ACTIVITY_NEW_TASK属性,来启动一个新的Activity栈。

2.singleTop

栈顶复用模式:在这种模式下,如果新启动的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,只会重新调用onNewIntent方法,这个Activity的onCreate、onStart都不会被系统调用。如果新Activity实例已经存在但不在栈顶,那么重新创建Activity并放入栈顶。

3.singleTask

栈内复用模式:这是一种单实例模式,一个栈中同一个Activity只存在唯一一个实例,无论是否在栈顶,只要存在实例,都不会重新创建,和singleTop一样会重新调用onNewIntent方法。需要注意的是:如果一个Activity被设置为singleTask模式,那么当栈内已经存在该Activity实例时,再启动该Activity,会让该Activity实例之上的Activity被出栈。举个例子:有四个Activity分别是A、B、C和D,A是singleTask模式,当先执行A->B->C->D时,A在栈内已存在实例,此时再调用D->A启动A时,会让A实例之上的B、C、D都出栈。一般项目的MainActivity都设置为此模式,方便放回首页和清空中间Activity。

4.singleInstance

单实例模式:这是一种加强的singleTask模式,它除了具有singleTask模式的所有特性外,还加强了一点,那就是此种模式的Activity只能单独地位于一个任务栈中,不同的应用去打开这个activity共享公用的同一个activity。他会运行在自己单独、独立的任务栈里面,并且任务栈里面只有他一个实例存在。应用场景:呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。或者你确定你需要使Activity只有一个实例。

当屏幕旋转或切换系统语言时,Activity生命周期会经历销毁再重建,但是ViewModel里面的变量值时不受影响的。说明ViewModel中的数据在此期间进行了存储,在之后又进行了恢复。

我们一般在Activity的onCreate中获取ViewModel的实例

valviewModel=ViewModelProvider(this).get(MainViewModel::class.java)在ViewModelProvider中重点会调用ensureViewModelStore,如下图:

ViewModelProvider会调用ensureViewModelStore(),该方法中有两个很重要的类:ViewModelStore和NonConfigurationInstances

ViewModelStore是用来存储ViewModel对象的,记得内部应该是一个HashMap,用于缓存ViewModel的实例对象。

NonConfigurationInstances实际是一个JavaBean类,内部存储了viewmodelStore。

具体的执行流程在.get(MainViewModel::class.java)中,根据Key从ViewModelStore获取缓存的ViewMode,如果存在,就返回ViewModel实例,如果不存在当前的Class实例,则用工厂方法创建一个,再将新创建的加入缓存。

屏幕旋转前后,mViewModelStore在屏幕旋转前后都是同一个对象,会在NonConfigurationInstances.onRetainNonConfigurationInstance()中保存数据。

屏幕旋转后,Activity重建后从getLastNonConfigurationInstance()中获取到了屏幕旋转前保存的NonConfigurationInstances实例对象,然后从nc对象中获取存储的mViewModelStore对象。

THE END
1.SketchUp运转速度慢,为什么?BIM免费教程5. 清理缓存:定期清理SketchUp的缓存文件,可以提高软件的运行速度。 6. 关闭其他程序:关闭在运行SketchUp时不必要的后台程序,以释放系统资源。 7. 使用合适的视图样式:选择合适的视图样式,如简化线框或隐藏线框,可以提高运行速度。 SketchUp运转速度慢的原因: https://www.tuituisoft.com/jianzhu/51253.html
2.APP性能测试方法速度app流畅度APP性能测试是保证APP用户体验的关键一环,通过测试可以发现并解决APP在运行过程中的性能瓶颈,提升用户满意度。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 性能测试的意义 发现性能瓶颈:找出APP在运行过程中耗时较长的环节,如启动时间、页面加载时间、响应时间等。 https://www.163.com/dy/article/JBALKO12055626UU.html
3.数据库为什么运行的很慢帆软数字化转型知识库数据库 为什么运行的很慢 数据库运行缓慢的原因有很多,主要包括硬件限制、索引使用不当、查询优化不足、数据库配置不佳、数据量过大、锁竞争、网络延迟、磁盘I/O瓶颈等。其中,硬件限制是一个常见的原因。例如,数据库服务器的CPU、内存或磁盘性能不足,都会导致数据库运行缓慢。详细来说,内存不足可能会导致频繁的https://www.fanruan.com/blog/article/274794/
4.双非本科跨专业5面京东,8600小时后收到通知,流下喜悦泪水3、本科参加比赛较多,电子设计大赛,大学生数学竞赛等,没有程序相关的比赛经历。 4、由于身边的人大多数从事程序员行业,自己其实也很纠结,于是疫情期间(2020年4月份)开始零基础看Java,由于个人原因,5、6月份也没怎么学习,断断续续刷了点题(真后悔5、6月份没好好刷题)。还狠狠地梳理了一遍知识体系 https://maimai.cn/article/detail?fid=1632778078&efid=DWfu7WeSgiHv2qWOUabF1g
5.电脑调查报告中国电脑健康调查报告发布三慢症状让用户崩溃 二、运行慢 运行慢是很多用户都有切身体会的电脑健康问题。比如,文档打开时间过长、程序响应速度太慢,玩单机游戏也会卡、慢和跳帧,文件复制、解压缩等操作总是没完没了等等现象,都是电脑运行慢的典型症状。最近一年来,向360电脑专家求助解决此类问题的用户累计接近3230万https://www.unjs.com/fanwenwang/dcbg/20230303105128_6576063.html
6.计算机病毒论文计算机病毒会导致电脑的运行速度变慢,因为计算机的病毒在运行的时候不仅要占用内存,还会干扰计算机系统的正常运行,这就会使的计算机的运行速度变慢,还会有计算机卡机计算机黑屏的危险,这些计算机病毒能够控制计算机程序,当这个计算机程序被启动时这些隐藏在计算机程序内的计算机病毒就会开始执行他们的任务,破坏计算机原本的程序https://www.yjbys.com/bylw/jisuanji/156079.html
7.运维个人工作总结实用11篇1、在硬件条件允许的情况下安装网络流量检测软件,对局域网进行监测,及时发现网络故障和排错,使网络快速高效的运行。 2、在继续完善公司网络的同时,加强理论和业务知识学习,不断提高自身综合素质水平。把工作做到更好。 3、等省店全部搬离我们接管机房后,对公司所有电脑设备进行统一计算机名称,分单位部门给予不同的ip段https://www.liuxue86.com/a/5136520.html
8.我的国没有那么厉害——盘点亟待攻克的“卡脖子”核心技术应用牵引不足进步慢 环氧树脂情况特殊,“不同用途,其结构和性能等都不同。”孔振武说,我国碳纤维材料生产与应用相互脱节,应用对之牵引不足,没有反馈修正,环氧树脂等技术进步自然也就慢了。 目前,高端碳纤维用得最多的是在飞机上,如在波音B787机型上,使用东丽公司生产的碳纤维复合材料已占总材料用量的50%。2016年https://www.zhuanzhi.ai/document/1f90ea1d7e798e49cafcd8ec484699f2
9.4W字一文带你看懂智能座舱域控制主流芯片及平台架构汽车电子3) 基于传统分布式架构, 主机厂只是架构的定义者, 核心功能是由各个ECU完成, 其软件开发工作主要是由Tier 1完成, 主机厂只做集成的工作, 这也是为什么大部分主机厂基本没有软件开发能力的原因, 就靠DRE搞定供应商就能集成一辆车, 为什么还要花成本养一个软件团队。 https://www.eefocus.com/automobile-electronics/515901
10.计算机组装与维护实训报告范文3篇实习总结五、对故障检测方法,常见故障原因和排除的认识和体会: 对于我们来说,计算机运行过程中有无出现问题无疑决定着我们能否正常地使用它来完成各项工作,于是了解和认识相关的故障检测和排错知识变得十分之有必要,以下是我在本次实训过程中学习到的部分相关知识和步骤: 1. 计算机故障的检测原则 ? 计算机系统故障的检测原https://www.diyifanwen.com/fanwen/shixizongjie/4319201.html
11.图文并茂5W1H分析法帮你系统掌握缓存2.软件层面 为缓解 CPU 压力而做缓存:比如把方法运行结果存储起来、把原本要实时计算的内容提前算好、把一些公用的数据进行复用,这可以节省 CPU 算力,顺带提升响应性能。 为缓解 I/O 压力而做缓存:比如把原本对网络、磁盘等较慢介质的读写访问变为对内存等较快介质的访问,将原本对单点部件(如数据库)的读写访https://www.51cto.com/article/703216.html
12.测试面试题集成测试预置条件有个程序,在windows上运行很慢,怎么判断是程序存在问题,还是软硬件系统存在问题? 1、检查系统是否有中度的特征,如:浏览器窗口连续打开,系统中文件图标改成统一图标,CPU使用率保存90%以上等 2、检查软件/硬件的配置是否符合软件的推荐标准 3、确认当前的系统是否是独立,即没有对外提供什么消耗CPU资源的服务,如:虚拟https://blog.csdn.net/qesrdtcfvgb/article/details/111872603
13.《重构:改善既有代码的设计》读书笔记腾讯云开发者社区听起来可能有些反直觉,因为重构可能会花大量的时间改善设计、提高阅读性、修改 BUG,难道不是在降低开发速度嘛? 软件开发者交谈时的故事:一开始他们进展很快,但如今想要添加一个新功能需要的时间就要长得多。他们需要花越来越多的时间去考虑如何把新功能塞进现有的代码库,不断蹦出来的bug修复起来也越来越慢。代码库https://cloud.tencent.com/developer/article/1445777
14.节水灌溉知识问答管道输水中设计管径一般采用已生产的管径规格,为了运行经济,按经济流速法或限定流速法来确定管径。某级渠道能否用管道代替,要根据渠道流量和上述方法确定管径,如果在已生产的各类管道中有相近的管径规格即可用管道来代替该级渠道的输水,否则是不经济的。对多泥沙水源要考虑泥沙处理问题。 https://zm.jiceng.zhengzhou.gov.cn/031001003/7956391.jhtml