常见安卓知识点总结

1.安卓自定义控件的三种实现方式:(主要作用就是提高代码的复用性)

1)组合控件:顾名思义就是将一些小的控件组合起来形成新的控件,主要做法是继承某个布局控件,然后将需要的控件填充进去。例如:titlebar, 高亮按钮等

2)继承控件:保留继承控件的特性,引入新的特性来满足自己的需求,主要做法是继承某个控件,然后重写里面的某些方法来达到自己想要的效果。例如横向滑动删除listview等

3)自绘控件:在View的onDraw方法中完成绘制,主要有三个方法:onLayout()~控制部布局的位置有四个参数,onMeasure()~控制宽高,onDraw()绘制,主要有Paint类(画笔)和Canvas(画布)。

   1. Paint类:是android提供的绘图的一个工具类即画笔工具,它在绘图中有极其重要的作用,画笔工具主要指定    如何绘制我们所需要的图形,如图形的颜色、样式等。画笔对象有很多设置方法,大体上可以分为两类

  (1)与图形绘制相关

  (2)与文本绘制相关

  2.Canvas类:主要有rotate(),save(),restore等重要方法,画图的canvas和显示没关系,而这个canvas又只影响你画图,意思就是,画图,实际上是画在这个canvas定义的范围和规则下,但是其实图是画在显示在屏幕上的。我们进行的旋转只是旋转了坐标系而对之前所绘制的图形是没有影响的,影响的是旋转后我们所绘制的图形

### 2.Java栈,PC寄存器,本地方法栈,堆,方法区和运行常量池

链接地址:https://my.oschina.net/wangsifangyuan/blog/711329

链接(堆栈讲得特别清楚):https://www.cnblogs.com/ibelieve618/p/6380328.html

1)java栈(stack):栈的区域很小只有1M,特点是存取速度很快,所以在栈中都是快速执行的任务,**存放的是:基本数据类型、局部变量、函数调用**

2)PC寄存器( PC register ):每个线程启动的时候,都会创建一个PC(Program Counter,程序计数器)寄存器。PC寄存器里保存有**当前正在执行的JVM指令的地址**。

3)本地方法栈(Nativemethodstack):**保存native方法进入区域的地址**。

4)堆(heap):**new创建的实例化对象及数组**,是存放在堆内存中的,用完之后靠垃圾回收机制不定期自动消除

5)方法区(method) : 又叫静态区,存放所有的①类(class),②静态变量(static变量),③静态方法,④常量和⑤成员方法。

6)常量池(String Constant Pool):里存储着字面量和符号引用.在JDK6.0及之前版本,字符串常量池是放在Perm Gen区(也就是方法区)中,**存放字符串常量**;在JDK7.0版本,字符串常量池被移到了堆中了。至于为什么移到堆内,大概是由于方法区的内存空间太小了,既存放字符串常量也可以存放位于堆内的字符串对象的引用。

注意:需要说明的是:字符串常量池中的字符串只存在一份!

如:

String s1 = "hello,world!";

String s2 = "hello,world!";

即执行完第一行代码后,常量池中已存在 “hello,world!”,那么 s2不会在常量池中申请新的空间,而是直接把已存在的字符串内存地址返回给s2。

举例说明1:

**1. 首先JVM执行main()函数在栈中开辟一块空间存放x,同时赋值为1。

2. 接着执行show()函数在栈中开辟一块新空间存放x,同时赋值为2,此时main空间与show空间并存,同时运行,互不影响。

3. show函数执行完,变量x立即被释放掉,空间消失。但是main()函数空间仍然存在,main中的变量x仍然存在,不受影响。


举例说明2:

1.执行int[] x=new int[3],首先在栈中开辟一块空间存放x,地址值会赋给x,同时会在堆中开辟一块空间存放new int[3],堆内存会自动存储首地址值,所以x就指向了这个数组。

2.执行int[] y=x,然后再栈中开辟一块新空间存放y,同时将地址值赋给y,所以y和x都指向了同一个堆内存中的数组。执行y[1]=100,接着在堆内存中将100附给[1]这个数组元素,所以数组的三个元素值分别为0,100,0。

3. 执行x=null,即x的内存地址呗删除了,不再指向堆中的数组了,被视为垃圾,JVM会启动垃圾回收机制,不定时自动删除。但是y仍然指向堆中的数组,不会消失。**


举例说明3:

与举例说明2同理


### 3.安卓的事件分发机制

链接:https://www.jianshu.com/p/6baa9b2790d5

布局:Activity => ViewGroup => View

1) dispatchTouchEvent()分发事件:return super()(默认为false)、true(不分发)、false(分发) 。Android中所有的事件都必须经过这个方法的分发,然后决定是自身消费当前事件还是继续往下分发给子控件处理。返回true表示不继续分发,事件没有被消费。返回false则继续往下分发,如果是ViewGroup则分发给onInterceptTouchEvent进行判断是否拦截该事件,事件(多数情况)是从Activity的dispatchTouchEvent开始的。执行dispatchTouchEvent(ev),事件向下分发。

2) onIntercepterTouchEvent()拦截事件:return super()(默认为false)、true(拦截)、false(不拦截)

3) onTouchEvent()触摸事件: return super()(默认为false)、true(自己消费,事件终止)、false(不消费往下传,如果都不消费则往上传,全都不消费事件终止)

**注意:

1.Activity和View是没有onIntercepterTouchEvent这个事件,onTouchEvent()在dispatchTouchEvent()中被调用。

2.onTouch事件要先于onClick事件执行,onTouchEvent在事件分发方法dispatchTouchEvent中调用,而onClick在事件处理方法onTouchEvent中被调用,onTouchEvent要后于dispatchTouchEvent方法的调用。


**

实例如下图:在Activity中有一个ViewGroup1,嵌套着ViewGroup2,最上层是个View。当然那些DecorView、FrameLayout什么的就不说了。事件(多数情况)是从Activity的dispatchTouchEvent开始的。执行dispatchTouchEvent(ev),事件向下分发。



看下ViewGroup源码:

``` ViewGroup:

public boolean dispatchTouchEvent(MotionEvent event)

{

        if(onInterceptTouchEvent(event)){//是否拦截

            return onTouchEvent(event);

        }

        //没有拦截

        if(child==null){

            //没有子控件

            return onTouchEvent(event);

        }else{

            //执行子控件的dispatchTouchEvent

            boolean consume= child.dispatchTouchEvent(event);

            if(!consume){//子控件没有消费事件,执行当前view的onTouchEvent

                return onTouchEvent(event);

            }else{

                return false;

            }

        }

    }

    ```

4.Android中onTouch与onClick事件的关系

链接:https://blog.csdn.net/mydreamongo/article/details/30465613

例如:LinearLayout分别设置了onTouchListener,onClickListener,onLongClickListener及onTouchEvent回调。

1. onTouchListener是最先被触发的,然后是本身的onTouchEvent回调。当最后的up事件发生并被onTouchEvent处理后才会触发onClickListener。

2. 把onTouchEvent回调中的super.onTouchEvent去除,直接返回true,则onClickListener永远无法被触发,也侧面的说明了onclickListener的触发是在onTouchEvent回调中来实现的。

3. 当长按的时候,在onLongClick中返回false(默认),无需到up就会触发onLongClick的响应,之后会继续响应touch,但之后也会继续触发onClick的响应

4. 如果在onLongClick中返回true,则流程如下,即只在中间触发了onLongClick,之后会继续响应touch,但当up的时候就不会再触发onClick

### 5.安卓View的setEnabled和setClickable的思考

链接:https://blog.csdn.net/AndroidMsky/article/details/78072403?locationNum=9&fps=1

例如:imageview m1和m2, m2把m1覆盖了,二者设置onClick、onLongClick和onTouch事件

1.二者都注册setOnClickListener。结果是m2可以触发,m1不可以。这很简单。

2.在1.的基础上设置m2.setEnabled(false),则m1,m2都不可点,setOnTouchListener方法不会被调用

3. 当onClick和onLongClick都被监听的时候,setClickable为false不起作用,后者会强制将setClickable置为true。

4. 当只监听onClick时,m2.setClickable(false)则m2不可点,m1可点击

5. 在4.的基础上m2.setOnTouchListener返回为true,事件只被m2消费,m1接触不到事件,返回为false则为4.

### 6.快速排序的原理总结

链接:[http://www.cnblogs.com/hjy9420/p/5032309.html](http://www.cnblogs.com/hjy9420/p/5032309.html)

1.先找到一个数作为基准,定一个start和end

2.while循环,条件是end大于start,end-- 然后从最后往前找,找到一个比基准值小的进行交换。接着从前往后找,找到比基准值大的进行交换。

4.第一次结束后基准值前的比它小,基准值后面的比它大,都是乱序的。

5.然后把基准左边和右边的数采用递归继续上面的操作

### 7.三级缓存

内存缓存:优先加载,速度最快

本地缓存:次优先加载,速度较快

网络缓存:最后加载,速度较慢

1.内存缓存采用LruCache算法:它把最近使用的对象用“强引用”存储在LinkedHashMap中,并且把最近最少使用的对象在缓存值达到预设定值之前就从内存中移除。

2.加载图片时,首先采用LRU方式进行寻找,若找不到指定内容,则进行本地搜索,若本地也找不到,向网络发起请求来获取图片。

### 8.picasso、Glide和Fresco的区别

链接:[https://www.cnblogs.com/baiqiantao/p/6808457.html](https://www.cnblogs.com/baiqiantao/p/6808457.html)

Picasso:由Square公司开源的一款图片加载和缓存的库,不过Picasso不支持磁盘缓存.也就是说如果想要做磁盘缓存的话需要另外想办法.(可以利用JakeWharton/DiskLruCache)

Glide:一款和Picasso类似的图片加载和缓存的开源库.虽然在函数定义和调用上和Picasso相差无几,但是Glide确实在性能方面比Picasso要好,值得注意的是Glide库仅支持Android 2.3.3及以上的版本。Glide默认的Bitmap格式是RGB_565,比ARGB_8888格式的内存开销要小一半。

Fresco:Fresco 中设计有一个叫做 image pipeline 的模块。它负责从网络,从本地文件系统,本地资源加载图片。为了最大限度节省空间和CPU时间,它含有3级缓存设计(2级内存,1级文件)。Fresco 中设计有一个叫做 Drawees 模块,方便地显示loading图,当图片不再显示在屏幕上时,及时地释放内存和空间占用

Fresco相比其他图片库如Picasso,UIL,Glide相比,所具有的最重要的几个独有特性:

在Android 5.0以下系统,图片不存储在Java heap,而是存储在ashmemheap,中间的字节buffer同样位于native heap。使应用有更多内存空间,降低OOM风险,减少GC次数。渐进式的JPEG呈现。

图片可以在任意点进行裁剪,而不是中心,即自定义居中焦点。

JPEG可以在native进行resize,避免了在缩小图片时的OOM风险。

支持Gif和WebP。

### 9.Android图片质量压缩和尺寸压缩

链接:[https://blog.csdn.net/sinat_21198467/article/details/52812988](https://blog.csdn.net/sinat_21198467/article/details/52812988)

```

/**

* 压缩图片质量(大小不变)

* @param image 需要压缩的图片

* @return Bitmap 压缩后的图片

* */

private static Bitmap doCompressImage(Bitmap image) {

ByteArrayOutputStream baos = new ByteArrayOutputStream();

image.compress(Bitmap.CompressFormat.JPEG, 70, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中

int options = 50;

while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩

baos.reset();// 重置baos即清空baos

image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中

if (options > 0)

options -= 10;// 每次都减少10

else

break;

}

ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中

Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片

return bitmap;

}

/**

* 压缩图片大小(缩小为原来的1/5)

* @param srcPath 需要压缩的图片路径

* @return Bitmap 压缩后的图片

* */

public static Bitmap compressImage(String srcPath) {

BitmapFactory.Options newOpts = new BitmapFactory.Options();

// 开始读入图片,此时把options.inJustDecodeBounds 设回true了

newOpts.inJustDecodeBounds = true;

Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 此时返回bm为空

newOpts.inJustDecodeBounds = false;

int w = newOpts.outWidth;

int h = newOpts.outHeight;

float hh = 266;

float ww = 426;

/*float hh = h / 5;// 缩小5倍

float ww = w / 5;// 缩小5倍

*/ // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可

int be = 1;// be=1表示不缩放

if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放

be = (int) (newOpts.outWidth / ww);

} else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放

be = (int) (newOpts.outHeight / hh);

}

if (be <= 0)

be = 1;

newOpts.inSampleSize = be;// 设置缩放比例

// 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了

bitmap = BitmapFactory.decodeFile(srcPath, newOpts);

return doCompressImage(bitmap);// 压缩好比例大小后再进行质量压缩

}

```

### 10.安卓中图片占内存大小怎么计算

链接:[http://www.cnblogs.com/dasusu/p/9789389.html ](http://www.cnblogs.com/dasusu/p/9789389.html)

**一张图片(BitMap)占用的内存=图片长度*图片宽度*单位像素占用的字节数**

1).单位像素:ALPHA_8 -- (1B)、RGB_565 -- (2B)、ARGB_4444 -- (2B)、ARGB_8888 -- (4B)、RGBA_F16 -- (8B)

注意:这里像素点大小以 4B 来计算是因为,当没有特别指定时,系统默认为 ARGB_8888 作为像素点的数据格式

2)dpi、分辨率与图标尺寸的关系

L DPI ( 120 DPI )—分辨率240*320px,其启动图标大小为 36 x 36 px

M DPI (160 DPI )—分辨率320*480px,其启动图标大小为 48 x 48 px

H DPI ( 240 DPI )—分辨率480*800px,其启动图标大小为 72 x 72 px

XH DPI ( 320 DPI )—分辨率1280*720px,其启动图标大小为 96 x 96 px

XXH DPI( 480 DPI )—分辨率1920*1080px,其启动图标大小为144 x 144 px

3)名称 对应 DPI 比例(以 mdpi 为基数 1) 和px的换算关系

lpdi 120 DPI 0.75             1 dp = 0.75 px

mdpi 160 DPI 1                 1 dp = 1 px

hdpi 240 DPI 1.5                 1 dp = 1.5 px

xhdpi 320 DPI 2                 1 dp = 2 px

xxhdpi 480 DPI 3                 1 dp = 3 px

xxxhdpi 640 DPI 4                 1 dp = 4 px

2)通常情况下图片会放在res的不同目录中,而同一张目录放在不同的目录下BitMap占用的内存也不一样,以1080*452这张图为例:

新图的高度 = 原图高度 * (设备的 dpi / 目录对应的 dpi )

新图的宽度 = 原图宽度 * (设备的 dpi / 目录对应的 dpi )

内存大小:转换后的分辨率:1080 * (240/160) * 452 * (240/160)*4B = 1620 * 678*4B

总结:首先看你手机的分辨率得出对应的密度值,然后看这张图片放在res哪个文件夹下,将手机的密度值和图片所在文件夹的密度值进行对比得出比值然后乘以图片宽高得出转换后的分辨率,再乘以单位像素占用的字节数(4b)

### 11.http和https有什么区别

链接:[https://blog.csdn.net/csdn_huzeliang/article/details/79060429](https://blog.csdn.net/csdn_huzeliang/article/details/79060429)

常见的加密算法:对称的:DES、3DES、AES(可逆) 非对称:MD5、RSA、SHA(不可逆)

HTTPS和HTTP的区别主要如下:

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

3、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

4、HTTP 的 URL 以 http:// 开头,而 HTTPS 的 URL 以 https:// 开头

5、在 OSI 网络模型中,HTTP 工作于应用层,而 HTTPS 工作在传输层

### 12.stackoverflowerror是什么错误

StackOverflowError :如果一个线程在计算时所需要用到栈大小 > 配置允许最大的栈大小,那么Java虚拟机将抛出StackOverflowError。一般发生在当应用程序递归太深而发生堆栈溢出时,应该减少递归算法的次数以判断错误所在

OutOfMemoryError:内存溢出错误,如果不能提供足够的内存来为新线程创建初始的本机方法堆栈,那么Java虚拟机将抛出OutOfMemoryErro

### 13.Activity的启动流程

1.Launcher通知AMS启动APP的MainActivity,也就是清单文件设置启动的Activity。

2.AMS记录要启动的Activity信息,并且通知Launcher进入pause状态。

3.Launcher进入pause状态后,通知AMS已经paused了,可以启动APP了。

4.app未开启过,所以AMS启动新的进程,并且在新进程中创建ActivityThread对象,执行其中的main函数方法

5.app主线程启动完毕后通知AMS,并传入applicationThread以便通讯。

6.AMS通知APP绑定Application并启动MainActivity。

7.APP启动MainActivitiy,并且创建和关联Context,最后调用onCreate方法。

### 14.Android跨进程通信的四种方式

Android系统中应用程序之间不能共享内存,在android SDK中提供了4种用于跨进程通讯的方式。这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和Service。

1.activity:需要指定的是要访问的Activity所对应的Action(一个字符串)。有些Activity还需要指定一个Uri(通过 Intent构造方法的第2个参数指定)

2.Content Provider

3.广播(Broadcast)

4.AIDL服务

### 15.如何传递大型数据

方法一:将需要传递的数据写在临时文件或者数据库中,再跳转到另外一个组件的时候再去读取这些数据信息,这种处理方式会由于读写文件较为耗时导致程序运行效率较低;

方法二:将需要传递的数据信息封装在一个静态的类中(注意当前组件和要跳转到的组件必须属于同一个进程,因为进程之间才能够共享数据),在当前组件中为类设置内容,然后再跳转到的组件中去取,这种处理方式效率很高,但是会破坏程序的独立性。

方法三:EventBus

### 16.https加密过程:

单向认证:1.客户端给服务端发送SSL版本等信息2.服务端给客户端返回SSL版本、随机数等信息以及服务器证书3.客户端校验服务端证书合不合法,不合法警告,合法继续4.客户端发送自己可支持的加密方案给服务端选择,服务端选择好加密方案以明文方式发给客户端5.客户端收到加密方案后产生随机码,作为加密密钥,然后用服务端公钥对该秘钥进行加密发给服务端6.服务端用私钥进行解密,获得对称加密的秘钥7.双方可以用对称密钥进行加解密

双向认证:1.客户端给服务端发送SSL版本等信息2.服务端给客户端返回SSL版本、随机数等信息以及服务器证书3.客户端对服务端证书进行校验,合法继续,不合法警告4.客户端将自己的证书和公钥发送给服务端5.服务端对客户端证书进行校验,校验结束后获得公钥6.客户端发送可支持的加密方案给服务端选择,服务端选好方案用客户端公钥进行加密发送给客户端7.客户端用证书的私钥进行解密,产生随机码,作为对密钥,使用服务器公钥对密钥加密发送给服务端8.服务端用私钥对加密信息进行解密,获得对称的密钥。9.双方可以用对称密钥进行加解密

### 17.java的四种引用状态

1、强引用

代码中普遍存在的类似"Object obj = new Object()"这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。

2、软引用

描述有些还有用但并非必需的对象。在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。Java中的类SoftReference表示软引用。

3、弱引用

描述非必需对象。被弱引用关联的对象只能生存到下一次垃圾回收之前,垃圾收集器工作之后,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。Java中的类WeakReference表示弱引用。

4、虚引用

这个引用存在的唯一目的就是在这个对象被收集器回收时收到一个系统通知,被虚引用关联的对象,和其生存时间完全没关系。Java中的类PhantomReference表示虚引用。

### 18.垃圾回收算法

1.标记-清除(Mark-Sweep)算法:分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,标记完成后统一回收所有被标记的对象,缺点:标记清除后会产生大量不连续的内存碎片,轮巡效率不高。

2.复制(Copying)算法:它将可用的内存分为两块,每次只用其中一块,当这一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已经使用过的内存空间一次性清理掉,缺点:内存缩小的一半

3.标记-整理(Mark-Compact)算法:让所有存活对象都向一端移动,然后直接清理掉边界以外的内存

4.分代收集算法

### 19.IntentService 和Service

1.Service:

1)startService: 启动服务后,会执行如下生命周期:onCreate() ->onStartCommand() -> onStart()(现在已经废弃) -> onDestroy() 。

startService 方式启动的服务,服务会无限期的在后台运行,直到通过stopService 或 stopSelf 来终止服务。

2)bindService 绑定服务 和startService 的生命周期是不一样,bindServie 的生命周期如下:onCreate -> onBind -> onUnbind ->onDestroy。其中重要的就是onBind 和onUnbind 方法。

2. IntentService: IntentService是Service 的子类,默认给我们开启了一个工作线程执行耗时任务,并且执行完任务后自 动停止服务。扩展IntentService比较简单,提供一个构造方法和实现onHandleIntent 方法就可了,不用重写父类的其他方法。但是如果要绑定服务的话,还是要重写onBind 返回一个IBinder 的。使用Service 可以同时执行多个请求,而使用IntentService 只能同时执行一个请求。

总结:intentService其实就是对service的一个封装,在onStartCommand方法中开了一个子线程,然后执行完后stopSelf。使用Service 可以同时执行多个请求,而使用IntentService 只能同时执行一个请求

### 20.自定义view点击控件的时候可以改变它的宽高,并且还要改变它的内容

1.在调用 requestLayout() 方法时,view 只会执行 onMeasure(先)及 onLayout(后)方法

2.调用 invalidate ()方法时,view 会调用 onDraw()方法

### 21. 客户端常见的返回码的含义

2xx:请求正常,可能数据不全;3xx:请求重定向,除了304:客户端的请求条件不满足;4xx:请求出现问题;5xx:服务器出现问题

### 22.解决MVP presenter持有view对象导致oom

1.在activity或者fragment的destroy方法中view=null;

2.在presenter中将view转化为弱类型的对象,封装一个detach方法调用clear()方法释放,在activity或者fragment的destroy方法中调用

### 23.SharedPreferences数据存储的apply()和commit()区别

这两个方法的区别在于:

1. apply没有返回值而commit返回boolean表明修改是否提交成功

2. apply是将修改数据原子提交到内存, 而后异步真正提交到硬件磁盘, 而commit是同步的提交到硬件磁盘,因此,在多个并发的提交commit的时候,他们会等待正在处理的commit保存到磁盘后在操作,从而降低了效率。而apply只是原子的提交到内容,后面有调用apply的函数的将会直接覆盖前面的内存数据,这样从一定程度上提高了很多效率。

3. apply方法不会提示任何失败的提示。

由于在一个进程中,sharedPreference是单实例,一般不会出现并发冲突,如果对提交的结果不关心的话,建议使用apply,当然需要确保提交成功且有后续操作的话,还是需要用commit的。

1)会返回执行结果(2)如果不考虑结果并且是在主线程执行可以考虑apply

### 24.安卓版本的特性

链接:[https://blog.csdn.net/heiya0409/article/details/52794458](https://blog.csdn.net/heiya0409/article/details/52794458)

1.Android6.0引入的动态权限控制,指纹识别

2.Android7.0的“私有目录被限制访问”,VR支持:(FileUriExposedException异常)适配方式

1)第一步:在manifest清单文件中注册provider

2)第二步:指定共享的目录,这个目录必须和manifest注册的provider所引用的resource保持一致

3)第三步:使用FileProvider,将文件保存到指定URI

3.Android8.0:画中画模式(多用于视频),lamda表达式

### 25.redux的总结

链接:[redux快速上手](https://segmentfault.com/a/1190000011474522?utm_source=tag-newest)

Redux是一个JavaScript库,用于管理应用的前端状态。

三个特性:单一数据源,一个应用只有一个store;State是只读的,state的改变只能通过出发特定的action完成;使用reducer纯函数来执行修改。

1)可以将多个reducer函数放到一个对象中然后通过combineReducers来创建一个总的reducer然后通过createStore来创建store。

2)reducer中有state(当前state的数据)和action参数(action中有type字符串和payload参数,type用于区分action的各种操作如:增、删、改;payload是需要修改的state的数据)

3)store.dispatch(action)来修改对应state的状态(在我们分发消息之前,我们添加一些代码,让我们能够通过subscribe方法来监听store事件的更改。)

### 26.String不可变的原因

String 不可变时因为其String类和内部的CHAR型数组都用的final去修饰,String用final修饰时为了不能被继承char型数组用final修饰,使得其指针不得修改指向的堆地址,但是在堆内部的数组里面时可以变换数值的。

1)常量池 2)哈希码 3)安全性

### 27.Android各版本对应的SDK和JDK版本

Android 8.0 26 Oreo

Android 7.1 25 Nougat

Android 7.0 24 Nougat

Android 6.0 23 Marshmallow

Android 5.1 22 Lollipop

Android 5.0 21 Lollipop

Android 4.4 19

### 28.volatile关键字和synchronized关键字的区别

链接:[synchronized](https://www.cnblogs.com/xujingyang/p/6565606.html)

注意:synchronized作用在方法和代码块上的区别:作用在方法上范围更大,作用在同步代码块上范围小,范围越大,性能越差

1、volatile只能作用于变量,使用范围较小。synchronized可以用在变量、方法、类、同步代码块等,使用范围比较广。

2、volatile只能保证可见性和有序性,不能保证原子性。而可见性、有序性、原子性synchronized都可以包证。

3、volatile不会造成线程阻塞。synchronized可能会造成线程阻塞。

### 29.广播接收者的注册方式的区别

四大组件中,只有广播接收者是一个非常特殊的组件,其他3大组件都需要在清单文件中注册;

广播接收者,有2中注册方式:清单文件与代码方式,区别:

1)清单文件注册广播接收者,只要应用程序被部署到手机上,就立刻生效,不管进程是否处于运行状态;

2)代码方式,如果代码运行了,广播接收者才生效,如果代码运行结束,广播接收者,就失效;

这属于动态注册广播,临时用一下,用的时候,register,不用时unregister;

### 30. == 和 equals的区别

== :比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。

1、比较的是操作符两端的操作数是否是同一个对象。

2、两边的操作数必须是同一类型的(可以是父子类之间)才能编译通过。

3、比较的是地址,如果是具体的阿拉伯数字的比较,值相等则为true,如:

int a=10 与 long b=10L 与 double c=10.0都是相同的(为true),因为他们都指向地址为10的堆。

equals: 首先比较对象引用是否相等。除了String和Integer等包装类(对equals进行过处理,除了比较对象引用,还要比较对象内容)外,其他对象的equals和==没区别。也就是说(除了基本数据类型),两个值能用 == 就可以用equals,反过来不一定。

### 31.Java包装类、拆箱和装箱

基本数据类型变成包装类装箱;包装类变成基本数据类型叫拆箱

Integer obj = new Integer(m); // 手动装箱

int n = obj.intValue(); // 手动拆箱

Integer obj = m; // 自动装箱

int n = obj; // 自动拆箱

### 32.安卓的热修复框架有哪些

hotfix、Sophix、Tinker(微信开源)、Amigo(饿了么开源冷)

### 33.常见的布局性能优化工具

hierarchy(布局),systrace(内存泄漏),手机设置里的显示布局,leakcanary(检测内存泄漏的工具),as自带的Android Profiler检测cpu和内存使用情况

34.webview拦截注入

链接:https://blog.csdn.net/lowprofile_coding/article/details/77928614

webView.addJavascriptInterface(this,"android");//添加js监听 这样html就能调用客户端

@JavascriptInterface //仍然必不可少 public void getClient(String str){

        Log.i("ansen","html调用客户端:"+str);

    }

你可能感兴趣的:(常见安卓知识点总结)