1.standard标准模式:每次创建一个activity都会重新创建一个新的实例,不管这个实例是否已经存在。
2.singleTop栈顶复用模式:如果activity已经位于任务栈的栈顶,那么此activity不会被重新创建,同时会调用onNewIntent方法,如果activity实例已经存在但不位于栈顶,那么activity仍然会被重新创建。
3.singleTask栈内复用模式:只要activity在一个任务栈中存在,那么多次启动此activity都不会重新创建实例,并回调onNewIntent方法,此模式启动activity,系统首先会寻找是否存在A想要的任务栈,如果不存在,就会重新创建一个任务栈,然后把创建号A的实例放到任务栈中,这种模式具有clearTask的功能,他会把在此activity之上的任务栈出栈。
4.singleInstance单实例模式:这是一种加强的singleTask模式,具有此种模式的activity只能单独地位于一个任务栈中,且此任务栈中只有唯一一个实例。
答案:FragmentPagerAdapter 的每个fragment会持久的保存在ftagmentManager中,只要用户可以返回到页面中,它都不会被销毁。因此适用于那些数据相对静态的页面,fragment数量也比较少的那种;fragmentStatePagerAdapter只保留当前页面,当页面不可见时,该fragment就会被消除,释放其资源。因此适用于那些数据动态性较大,占用内存较多,多fragment的情况。
答案:先从内存中读取,如果没有从磁盘中读取,如果没有从网络获取显示,我们应该考虑哪些应该缓存,获取成本,缓存成本,缓存的价值。哪些应该丢弃?什么时候丢弃?这个时候我们就需要考虑到算法了。
1.LRU算法:(最近最少使用算法)算法的核心思想就是最近最少使用。它在算法的内部维护了一个LinkHashMap的链表,通过put数据的时候判断内存是否已经满了,如果满了,则将最近最少使用的数据给剔除掉,从而达到内存不会爆满的状态。因为LinkHashMap内部是一个数组双向链表的形式来存储数,他能够保证插入时候的数据和取出来的时候数据的顺序性一致,也就是说我们以什么样的顺序插入数据,就会以什么样的顺序取出数据。并且最重要的一点是,当我们通过get方法获取数据的时候,这个获取的数据会从队列中跑到队列头来,从而很好的满足我们LRUCache算法的设计思想。
2.LFU算法(最近不经常使用原则):使用次数最少的,当内存不足时会首先被干掉。
举例说明:我们熟悉的GLide图片加载框架就是使用LRuCache算法,内部也是基于LinedHashMap来实现的。
1.当不设置activity的android:configCahnges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次。
2.当设置activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横,竖屏时只会执行一次。
3…当设置activity的an。droid:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法。
一.非对称密钥加密的使用过程:
A要向B发送信息,A和B都要产生一对用于加密和解密的公钥和私钥。A要给B发送信息时,A用B的公钥加密信息,B收到这个消息后,B用自己的私钥解密A的消息,其他所有收到这个报文的人都无法解密,因为只有B才有B的私钥。 反过来,B向A发送消息也是一样。
二.对称加密和非对称加密的区别 :
1.对称加密加密与解密使用的是同样的密钥,所以速度快,但由于需要将密钥在网络传输,所以安全性不高。
2.非对称加密使用了一对密钥,公钥与私钥,所以安全性高,但加密与解密速度慢。
3.解决的办法是将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到 对称加密的密钥,然后双方可以使用对称加密来进行沟通。
答案:当Service中执行耗时操作时,20s会产生ANR,而IntentService是一个特殊的Service,则可用于执行后台耗时的任务,无需处理多线程问题,IntentService封装了HandlerThread和Handler,通过复写onHandleIntent方法操作耗时操作, 当任务执行完后会自动停止,无需调用stopSelf()方法停止Service,避免了Service的内存泄漏,Intentservice若未执行完成上一次的任务,将不会新开一个线程,是等待之前的任务完成后,再执行新的任务,等任务完成后再次调用stopSelf,适合执行一些高优先级的后台任务,因为不容易被杀死。
答案:减少onCreate的时间,耗时操作,移除背景,在很多的应用一开始点击的时候总会出现黑屏或者白屏,甚至前段时间微信也有同样的问 题。其实白屏或者黑屏还是一些其他的东西,都是因为 Android 主题的问题,只要自己自 定义一个启动主题,问题完美解决。
答案:Application Not Responding,"应用无响应"对话框。
1.产生原因:Activity 5s、Service 10s、Broadcast 20s
2.如何解决:分析log,/data/anr/traces.txt,主要看main Thread CPU usage和是否block死锁
3.如何避免ARN?
3.1.UI线程尽量只做跟UI相关的工作
3.2.耗时的工作(比如数据库操作,I/O,连接网络或者别的有可能阻碍UI线程的操作)把它放入单独的线程处理
3.3.尽量用Handler来处理UIthread和别的thread之间的交互。
答案:SparseArray不需要开辟内存空间来额外存储外部映射,从而节省内存。仅仅提高内存效率,而不是提高执行效率,所以也决定它只适用于android系统(内存对android项目有多重要,地球人都知道)。SparseArray执行效率比 HashMap要慢一点,因为查找需要折半查找,而添加删除则需要在数组中执行,而HashMap都是通过外部映射。
一.效率比较
1.entrySet的方式整体都是比keySet方式要高一些;
2.单纯的获取key来说,两者的差别并不大,但是如果要获取value,还是entrySet的效率会更好,因为keySet需要从map中再次根据key获取value,而entrySet一次都全部获取出来;
3.iterator的迭代器方式比foreach的效率高。
二、foreach和iterator
其实foreach的语法只是对iterator进行了简单的包装,使用起来更加方便而已,但是如果在foreach循环体内,对集合元素进行删除添加操作的时候,会报出ConcurrentModificationException,并发修改异常。如果需要在遍历集合的时候对象集合中元素进行删除操作,需要使用iterator的遍历方式,iterator自带的remove删除方式不会报出异常。
1、组合控件。这种自定义控件不需要我们自己绘制,而是使用原生控件组合成的新控件。如标题栏。
2、继承原有的控件。这种自定义控件在原生控件提供的方法外,可以自己添加一些方法。如制作圆角,圆形图片。
3、完全自定义
1.自定义属性的声明与获取:
分析需要的自定义属性,在res/values/attrs.xml定义声明, 在layout.xml文件中使用,在view的构造方法中进行获取。
2.测量onMeasure:
设置测量模式,从MeasureSpec中获取 EXACTLY→match_parent,AT_MOST→wrap_content,UNSPECIFIED不受限制,三种模式。调用ViewGroup中的onMeasure方法。在方法中调用了measureChild方法,执行了所有子控件的onMesure方法测绘出所有的子控件的大小。调用setMeasureDimension方法 设置测绘后的大小。
3.布局onLayout(ViewGroup):
决定子view的位置,尽可能将onMeasure中操作移动到此方法中,比如耗时,初始化等操作,因为此方法只执行一次,调用requestLayout(),会调用measure()过程 和 layout()过程
4.绘制onDraw:
使用canvas和paint画笔进行绘制,invalidate()可在U线程调用, postInvalidate()在子线程中调用,重绘,假如视图发生大小没有变化就不会调用layout()过程,只调用onDraw过程。
事件的分发过程是自上而下,由外向内的,事件总是先传递给父元素,由父元素分发给子view。
1.当一个viewGroup需要处理事件时如果onInterceptTouchEvent方法返回true,表示要拦截当前事件,则viewGroup的onTouchEvent方法会被调用,如果返回false,就会传递给它的子元素,子元素的onInterceptTouchEvent方法会被调用 。
2.当一个view需要处理事件时,如果它设置了onTouchListener,那么onTouchListener的onTouch方法会被调用,如果返回onTouch返回false,则当前view的onTouchEvent方法会被调用,如果返回true,将不会调用。
比如我们要在项目中把密钥等一些私密信息存储到.so文件中,那我们如何生成.so文件并调用呢?主要分为以下几个步骤:
1.新建AppSecrectUtils.class,编写调用c文件的方法,使用 System.loadLibrary加载.so文件,定义native方法。
2.make project 生成对应的.class文件。
3.根据.class文件生成.h文件,找到项目路径,进入命令输入页面, javah -d jni -classpath 编译后的class文件的绝对路径。
4.根据AppSecretUtils类编写main.c文件。实现native的方法
5.添加Android.mk文件,可以定义.so文件的名称等。
6.添加aplication.mk文件,可以设置生成哪些类型的.so文件。
7.找到项目路径进入到命令提示符界面,然后输入 ndk-build命令,即可在项目的libs文件中生成.so文件。
8.在你的项目中新建一个路径,必须与生成.so文件时中的AppSecretUtils包名路径一致,然后新建一个类AppSecretUtils名字也是保持一致。使用 System.loadLibrary加载.so文件,定义生成.so文件时的native方法,然后就可以在项目中使用AppSecretUtils进行调用相应的方法了。
1.请求行、由方法字段、URL 字段 和HTTP 协议版本字段 3 个部分组成,他们之间使用空格隔开
2.请求头部、请求头部由关键字/值对组成,典型的请求头有:User-Agent:产生请求的浏览器类型;Accept-Encoding:客户端可接受的编码压缩格式; Host:请求的主机名.
3/空行 最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头;
4.请求包体 包体类型 Content-Type 和包体长度 Content-Length;
1.状态行、HTTP 协议版本字段、状态码和状态码的描述文本 3 个部分组成
2.响应头部、包含了服务器用来处理请求的软件信息及其版本 Connection:连接方式;
3.空行
4.响应包体 服务器返回给客户端的文本信息;
1.作用:handler用来处理主线程与子线程之间通信的工具
2.原理:handler封装了消息的发送,内部跟Looper进行关联,Handler负责发送消息,Looper负责接收Handler发送的消息,并直接把消息回传给Handler自己,MessageQueue就是一个存储消息的容器。
3.为什么要设计只能通过Handler机制更新UI呢? 最根本的目的就是解决多线程并发问题.
4.主线程中Looper的轮询死循环为何没有阻塞主线程?
ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的应用也就退出了。 因为Android 的是由事件驱动的,looper.loop() 不断地接收事件处理事件,每一个点击触摸或者说Activity的生命周期都是运行在 Looper.loop() 的控制之下,如果它停止了,应用也就停止了。只能是某一个消息或者说对消息的处理阻塞了 Looper.loop(),而不是 Looper.loop() 阻塞它。
1.HTTP协议使用默认80端口,HTTPS协议使用443端口
2.HTTPS协议需要到CA申请证书,一般免费的证书较少,需要交费
3.HTTP信息是明文传输,HTTPS使用具有安全性的SSL加密传输信息
4、http的连接很简单,是无状态的。Https协议是由SSL+Http协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。 (无状态的意思是其数据包的发送、传输和接收都是相互独立的。无连接的意思是指通信双方都不长久的维持对方的任何信息。)
https实现原理:
(1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
(2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
(3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
(4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
(5)Web服务器利用自己的私钥解密出会话密钥。
(6)Web服务器利用会话密钥加密与客户端之间的通信。
答案:invalidate是在ui线程中使用,postInvalidate在非ui线程种使用,使用invalidate更新view时需要配合handler来使用,但是postInvalidate是不需要的,在线程种可以直接使用,通过postInvalidate的源码可知,它也是使用到了handler来进行处理的。
答案:wait是Object的方法,wait是对象锁,锁定方法不让继续执行,当执行notify方法后就会继续执行,sellp是Thread的方法, sellp是使线程睡眠,让出cpu,结束后自动继续执行。