GitHub持续更新:(声明:本答案为个人收集与总结并非标准答案,仅供参考,如有错误还望指出,谢谢!如有重复可能是常问问题)
Arrays.asList不能add:
此ArrayList非彼ArrayList,这是一个内部类,但是类名也叫 ArrayList.Arrays.asList方法创建出来的 ArrayList
和真正我们平时用的 ArrayList只是继承自同一抽象类的两个不同子类,而 Arrays.asList创建的 ArrayList 只能做
一些简单的视图使用,不能做过多操作,所以 ArrayList的几种初始化方式里没有 Arrays.asList这一说。
subList 方法:
1.上面提到了那个问题和 subList的坑有异曲同工之妙,都是由于返回的对象并不是真正的 ArrayList类型,而是和 ArrayList
集成同一父类的不同子类而已。所以会产生第一个坑,就是把当把 subList返回的对象转换成 ArrayList 的时候。
2.当你在 subList 中操作的时候,其实就是在操作原始的 ArrayList。
3.如果你使用 subList 方法获取了一个子列表,这之后又在原始列表上进行了新增或删除的操作,这是,你之前获取到的
subList 就已经废掉了,不能用了,不能用的意思就是你在 subList 上进行遍历、增加、删除操作都会抛出异常,没错,
连遍历都不行了。其实与二坑的原因相同,subList 其实操作的是原始列表,当你在 subList 上进行操作时,会执行 checkForComodification
方法,此方法会检查原始列表的个数是否和最初的相同,如果不相同,直接抛出 ConcurrentModificationException异常。
常用的GC算法(引用计数法、标记-清除法、复制算法、标记-清除算法)
1.耗时操作本身并不会导致主线程卡死, 导致主线程卡死的真正原因是耗时操作之后的触屏操作, 没有在规定的时间内被分发。
2.Looper 中的 loop()方法, 他的作用就是从消息队列MessageQueue 中不断地取消息, 然后将事件分发出去。
Android动画目前分为三种:
1.Frame Animation 帧动画,通过顺序播放一系列图像从而产生动画效果,。图片过多时容易造成OOM(Out Of Memory内存用完)异常。
2.Tween Animation 补间动画(又叫view动画),是通过对场景里的对象不断做图像变换(透明度、缩放、平移、旋转)
从而产生动画效果,是一种渐进式动画,并且View动画支持自定义。
3.Accribute Animation 属性动画,这也是在android3.0之后引进的动画,在手机的版本上是android4.0就可以使用这
个动 画,通过动态的改变对象的属性从而达到动画效果。
补间动画和属性动画的区别:
补间动画只是改变了View的显示效果而已,并不会真正的改变View的属性。而属性动画可以改变View的显示效果和属性。
举个例子:例如屏幕左上角有一个Button按钮,使用补间动画将其移动到右下角,此刻你去点击右下角的Button,它是绝
对不会响应点击事件的,因此其作用区域依然还在左上角。只不过是补间动画将其绘制在右下角而已,而属性动画则不会。
View绘制分三个步骤:
顺序是:onMeasure,onLayout,onDraw。调用invalidate方法只会执行onDraw方法;调用requestLayout方法只会执行
onMeasure方法和onLayout方法,并不会执行onDraw方法。所以当我们进行View更新时,若仅View的显示内容发生改变且
新显示内容不影响View的大小、位置,则只需调用invalidate方法;若View宽高、位置发生改变且显示内容不变,只需调
用requestLayout方法;若两者均发生改变,则需调用两者,按照View的绘制流程,推荐先调用requestLayout方法再调用
invalidate方法。
onSaveInstanceState是用来保存UI状态的,你可以使用它保存你所想保存的东西,在Activity杀死之前,它一般在onStop
或者onPause之前触发,onRestoreInstanceState则是在onResume之前触发回复状态,至于复写这个方法后onCreate方法
是否会被调用。
1.Activity被杀死了,onCreate会被调用,且onRestoreInstanceState 在 onResume之前恢复上次保存的信息。
2.Activity没被杀死,onCreate不会被调用,但onRestoreInstanceState 仍然会被调用,在 onResume之前恢复上次保
存的信息。
onSaveInstanceState和onRestoreInstanceState 是一对兄弟,一个负责存储,一个负责取出.“不一定”是成对的被调用的。
standard:这个是android默认的Activity启动模式,每启动一个Activity都会被实例化一个Activity,并且新创建的
Activity在堆栈中会在栈顶。
singleTop:如果当前要启动的Activity就是在栈顶的位置,那么此时就会复用该Activity,并且不会重走onCreate方法,
会直接它的onNewIntent方法,如果不在栈顶,就跟standard一样的。如果当前activity已经在前台显示着,突然来了一
条推送消息,此时不想让接收推送的消息的activity再次创建,那么此时正好可以用该启动模式,如果之前activity栈中
是A–>B–>C如果点击了推动的消息还是A–>B–C,不过此时C是不会再次创建的,而是调用C的onNewIntent。而如果现
在activity中栈是A–>C–>B,再次打开推送的消息,此时跟正常的启动C就没啥区别了,当前栈中就是A–>C–>B–>C了。
singleTask:该种情况下就比singleTop厉害了,不管在不在栈顶,在Activity的堆栈中永远保持一个。这种启动模式相对
于singleTop而言是更加直接,比如之前activity栈中有A–>B–>C—D,再次打开了B的时候,在B上面的activity都会
从activity栈中被移除。下面的acitivity还是不用管,所以此时栈中是A–>B,一般项目中主页面用到该启动模式。
singleInstance:该种情况就用得比较少了,主要是指在该activity永远只在一个单独的栈中。一旦该模式的activity的
实例已经存在于某个栈中,任何应用在激活该activity时都会重用该栈中的实例,解决了多个task共享一个activity。其
余的基本和上面的singleTask保持一致。
Fragment与Activity关联主要有两种方式,一种是通过在Activity的布局文件中写入fragment控件,使用name属性指定
一个Fragment;
另一种是在java代码中动态的添加与删除Fragment。
线程间通信:
1)主线程中创建子线程,如果为内部类或匿名内部类(new Thread(){}.start())方式启动子线程,则可在子线程内部直
接调用主线程的成员变量、final修饰的局部变量;
2)若外部类(继承Thread接口的子线程类),可设置setter方法,主线程调用该方法通过参数传值。
3)子线程中向主线程通信,可通过主线程的handler发送信息或Runnable代码对象,或调用activity.runOnUiThread(){}
方式运行Runnable代码对象。
进程间通信:
1)隐式意图intent跨进程启动Activity,通过intent传递数据,通常以Uri形式;
2)ContentProvider内容提供者,提供其它进程调用增删改查数据的入口;
3)Broadcast广播,发送广播并通过intent传递数据
4)通过AIDL连接其它进程的Service服务
一、原理
内存溢出(Out of memory):系统会给每个APP分配内存也就是Heap size值,当APP所需要的内存大于了系统分配的内存,
就会造成内存溢出;通俗点就是10L桶只能装10L水,但是你却用来装11L的水,那就有1L的水就会溢出。
内存泄漏(Memory leak):当一个对象不在使用了,本应该被垃圾回收器(JVM)回收,但是这个对象由于被其他正在使用
的对象所持有,造成无法被回收的结果,通俗点就是系统把一定的内存值A借给程序,但是系统却收不回完整的A值,那就是
内存泄漏。
二、两者的关系
内存泄漏是造成内存溢出(OOM)的主要原因,因为系统分配给每个程序的内存也就是Heap size的值都是有限的,当内存
泄漏到一定值的时候,最终会发生程序所需要的内存值加上泄漏值大于了系统所分配的内存额度,就是触发内存溢出。
三、危害
内存溢出:会触发Java.lang.OutOfMemoryError,造成程序崩溃
内存泄漏:过多的内存泄漏会造成OOM的发送,同样也会造成相关UI的卡顿现象
四、造成的原因以及处理
A、大量的图片、音频、视频处理,当在内存比较低的系统上也容易造成内存溢出建议使用第三方,或者JNI来进行处理
B、Bitmap对象的不正确处理(内存溢出)不要在主线程中处理图片使用Bitmap对象要用recycle释放高效的处理大图
C、非静态匿名内部类Handler由于持有外部类Activity的引用所造成的内存泄漏根据WeakReference对象,对handler使
用弱引用,并且调用removeCallbacksAndMessages移除。
D、线程由于匿名内部类runnable持有activity的引用,从而关闭activity,线程未完成造成内存泄漏,把线程改成静态
内部类,调用WeakReference来持有外部资源。
E、BraodcastReceiver、File、Cursor等资源的使用未及时关闭在销毁activity时,应该及时销毁或者回收
F、static关键字修饰的变量由于生命周期过长,容易造成内存泄漏尽量少使用静态变量,一定要使用要及时进行制null处理
G、单列模式造成的内存泄漏,如context的使用,单列中传入的是activity的context,在关闭activity时,activity的
内存无法被回收,因为单列持有activity的引用在context的使用上,应该传入application的context到单列模式中,这
样就保证了单列的生命周期跟application的生命周期一样单列模式应该尽量少持有生命周期不同的外部对象,一旦持有该
对象的时候,必须在该对象的生命周期结束前制null。
1)使用dp、sp单位,带有一定的适配性,根据dpi自动适配屏幕
2)创建不同分辨率、dpi、屏幕方向等规格的value文件夹,及对应dimens文件
3)创建不同分辨率、dpi、屏幕方向等规格的layout
4)代码动态设置View控件的高度、宽度
5)使用weight权重属性,按照比例分配View布局
GC是垃圾回收的意思(gabage collection),内存处理器是编程人员容易出现问题的地方,忘记或者错误的内存回收导致
程序或者系统的不稳定甚至崩溃,java的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,java语
言没有提供释放已分配内存的俄显示操作方法。
包括:DOM(Document Object Modal)文档对象模型,SAX(Simple API for XML)。
DOM是一次性将整个文档读入内存操作,如果是文档比较小,读入内存,可以极大提高操作的速度,但如果文档比较大,那
么这个就吃力了。所以此时SAX应用而生,它不是一次性的将整个文档读入内存,这对于处理大型文档就比较就力了
switch可作用于char byte short int
switch可作用于char byte short int对应的包装类
switch不可作用于long double float boolean,包括他们的包装类
switch中可以是字符串类型,String(jdk1.7之后才可以作用在string上)
switch中可以是枚举类型
概述:构造方法存在于类中,给对象数据(属性)初始化;
特点:方法名与类名一样;无返回值无void;
默认构造方法:我们不创建一个构造方法时,系统默认提供一个无参构造;当我们创建一个构造方法时,系统不再提供无
参构造,所以在实际项目中,全部手动给出无参构造
重载:存在于在一个类中,方法名相同,方法参数的类型或个数不同
重写:存在于子父类中,方法名、方法参数、返回值全部相同
所以:构造方法可以重载,不能重写
在一个类中,可以有多个构造方法(方法参数不同) ,即重载,来实现对象属性不同的初始化;但是子类中不能定义一个
方法无void无返回值的方法,编译错误,即子类无法继承构造方法,但是子类的构造器中可以调用父类的构造方法(默认自动调用无参构造)
这个跟常量池没有关系,只要是new,都是重新分配堆空间,如果不区分栈和堆,这里创建了1个String Object。如果是
从jvm角度来说的话,它是创建了两个对象,String s是在栈里创建了一个变量,new String(“xyz”)是在堆里创建了一
个对象并被s引用到。
会在return中间执行!
try 中的 return 语句调用的函数先于 finally 中调用的函数执行,也就是说 return 语句先执行,finally 语句后执
行,但 return 并不是让函数马上返回,而是 return 语句执行后,将把返回结果放置进函数栈中,此时函数并不是马上
返回,它要执行 finally 语句后才真正开始返回!但此时会出现两种情况:
①、如果finally中也有return,则会直接返回并终止程序,函数栈中的return不会被完成!;
②、如果finally中没有return,则在执行完finally中的代码之后,会将函数栈中的try中的return的内容返回并终止程序;
catch同try;
public class Test1 {
public static void main(String[] args) {
try {
System.out.println(new Test1().testname());
} catch (Exception e) {
e.printStackTrace();
}
}
public String testname() throws Exception {
String t = "";
try {
t = "try";
System.out.println("try");
return t;
} catch (Exception e) {
// result = "catch";
t = "catch";
return t;
} finally {
System.out.println("finally");
// return t = "finally";
}
}
}
打印结果如下:
try
finally
try
将finally中的注释放开,打印结果如下:
try
finally
finally
1、Integer是int的包装类,int则是java的一种基本数据类型
2、Integer变量必须实例化后才能使用,而int变量不需要
3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
4、Integer的默认值是null,int的默认值是0
Java中交互方式分为同步和异步两种:
同步交互:指发送一个请求,需要等待返回,然后才能够发送下一个请求,有个等待过程;
异步交互:指发送一个请求,不需要等待返回,随时可以再发送下一个请求,即不需要等待。
区别:一个需要等待,一个不需要等待,在部分情况下,我们的项目开发中都会优先选择不需要等待的异步交互方式。
哪些情况建议使用同步交互呢?比如银行的转账系统,对数据库的保存操作等等,都会使用同步交互操作,其余情况都优
先使用异步交互,如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被
另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。当应用程序在对象上调用了一个需要花费很长时间来
执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。
启动一个线程是start()方法。
启动线程之后start()方法会去调用run方法内容。
区别:start是创建并启动一个线程,而run是要运行线程中的代码。
字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的
字节流在操作文件时,即使不关闭资源(close方法),文件也能输出,但是如果字符流不使用close方法的话,则不会输出任
何内容,说明字符流用的是缓冲区,并且可以使用flush方法强制进行刷新缓冲区,这时才能在不close的情况下输出内容
Exception:
1.可以是可被控制(checked) 或不可控制的(unchecked)。
2.表示一个由程序员导致的错误。
3.应该在应用程序级被处理。
Error:
1.总是不可控制的(unchecked)。
2.经常用来用于表示系统错误或低层资源的错误。
3.如何可能的话,应该在系统级被捕捉。
不能,一个对象的一个synchronized方法只能由一个线程访问。
对象的synchronized方法不能进入了,但它的其他非synchronized方法还是可以访问的。
ArrayList与Vector都实现的List接口,当不同的是ArrayList是线程不安全的,而Vector是线程安全的。
HashMap是线程不安全的,Hashtable是线程安全的,如果考虑性能的话使用HashMap,如果多个线程使用一个Map时,使用
Hashtable.HashMap可以使用null作为key与value的值,但Hashtable不行,如果那样用了,则会出现NullPointerException异常
String 对一串字符进行操作。不可变类。
StringBuffer 也是对一串字符进行操作,但是可变类。
String:是对象不是原始类型.为不可变对象,一旦被创建,就不能修改它的值.对于已经存在的String对象的修改都是重新创
建一个新的对象,然后把新的值保存进去.
String是final类,即不能被继承.
StringBuffer:
是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象它只能通过构造函数来建立,
StringBuffer sb = new StringBuffer();
note:不能通过付值符号对他进行付值.
Collection
List
ArrayList
LinkedList
Set
HashSet
TreeSet
Map
HashMap
TreeMap
Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)Map提供key到value的映射。
此时的生命周期跟清单文件里的Activity的配置有关系。
1)不设置Activity的android:configChanges时,切屏会重新调用各个生命周期默认首先销毁当前activity,然后重新加载。
2)设置Activity如下属性后,由onConfigurationChanged方法接管屏幕方向、尺寸、键盘显隐的配置改变,则切屏不会重新
调用各个生命周期,只会执行onConfigurationChanged方法。通常在游戏开发,屏幕的朝向都是写死的。
android:configChanges=“orientation|keyboardHidden|screenSize”
帧动画,Frame动画,指通过指定的每一帧的图片和播放时间,有序的进行播放而形成的动画效果
视图动画,也就是所谓的补间动画。指通过指定View的初始状态、变化时间、方式、通过一系列的算法去进行图片变换,
从而实现动画效果。主要有scale、alpha、Translate、Rotate四种效果。
注意:只是在视图层实现了动画效果,并没有真正改变View的属性
属性动画,通过不断地改变View的属性,不断重绘而形成动画效果。相比较视图动画,View的属性是真正改变了。
注意:Android3.0(API 11)以上才支持。
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定
的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义
的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,MessageQueue需要一个Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
Handler,Looper和MessageQueue就是简单的三角关系。Looper和MessageQueue一一对应,创建一个Looper的同时,会
创建一个MessageQueue。而Handler与它们的关系,只是简单的聚集关系,即Handler里会引用当前线程里的特定Looper
和MessageQueue。这样说来,多个Handler都可以共享同一Looper和MessageQueue了。这些Handler也就运行在同一个线
程里,每个线程一个Loop而 一个MessageQueue。
可以将dictionary.db文件复制到Eclipse Android工程中的res\raw目录中,所有在res\raw目录中的文件不会被压缩,
这样可以直接提取该目录中的文件。
使用openDatabase方法来打开数据库文件,如果该文件不存在,系统会自动创建/sdcard/dictionary目录,并将res\raw
目录 中的 dictionary.db文件复制到/sdcard/dictionary目录中。
openDatabase方法的实现代码如下:
private SQLiteDatabase openDatabase()
{
try
{
// 获得dictionary.db文件的绝对路径
String databaseFilename = DATABASE_PATH + "/" + DATABASE_FILENAME;
File dir = new File(DATABASE_PATH);
// 如果/sdcard/dictionary目录中存在,创建这个目录
if (!dir.exists())
dir.mkdir();
// 如果在/sdcard/dictionary目录中不存在
// dictionary.db文件,则从res\raw目录中复制这个文件到
// SD卡的目录(/sdcard/dictionary)
if (!(new File(databaseFilename)).exists())
{
// 获得封装dictionary.db文件的InputStream对象
InputStream is = getResources().openRawResource(R.raw.dictionary);
FileOutputStream fos = new FileOutputStream(databaseFilename);
byte[] buffer = new byte[8192];
int count = 0;
// 开始复制dictionary.db文件
while ((count = is.read(buffer)) > 0)
{
fos.write(buffer, 0, count);
}
fos.close();
is.close();
}
// 打开/sdcard/dictionary目录中的dictionary.db文件
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(
databaseFilename, null);
return database;
}
catch (Exception e)
{
}
return null;
}
在openDatabase方法中使用了几个常量,这些常量是在程序的主类(Main)中定义的,代码如下:
public class Main extends Activity implements OnClickListener, TextWatcher{
private final String DATABASE_PATH = android.os.Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/dictionary";
private final String DATABASE_FILENAME = "dictionary.db";
}
Context.startService()和Context.bindService
解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()–>onDestroy()方法
ContentProvider出现的原因是为了数据共享,它和sql主要区别为它可以自定义共享的文件的暴露,sql不具备设置共享数据的权限。
使用SharedPreferences存储数据
文件存储数据
SQLite数据库存储数据
使用ContentProvider存储数据
网络存储数据
同步执行的话,就是程序会呆板地从头执行到尾,耗时间的东西不执行完,程序不会继续往下走,等待时间长的话,有时候
就会造成失去响应了。
异步的好处,就是把一些东西,特别是耗时间的东西扔到后台去运行了(doInBackground),程序可以继续做自己的事情,
防止程序卡在那里失去响应。
同步是指两个线程的运行是相关的,其中一个线程要阻塞等待另外一个线程的运行。
异步的意思是两个线程毫无相关,自己运行自己的。
解决办法: 将非静态内部类、匿名内部类 改成静态内部类,或者直接抽离成一个外部类。
如果在静态内部类中,需要引用外部类对象,那么可以将这个引用封装在一个WeakReference中。
2.静态的View
解决办法: 在使用静态View时,需要确保在资源回收时,将静态View detach掉。
将Handler放入单独的类或者将Handler放入到静态内部类中(静态内部类不会持有外部类的引用)。如果想要在handler
内部去调用所在的外部类Activity,可以在handler内部使用弱引用的方式指向所在Activity,这样不会导致内存泄漏。
或者在onDestory时,调用相应的方法移除回调和删除消息。
4.监听器(各种需要注册的Listener,Watcher等)
解决办法: 在onDestory时,取消注册,editText.removeTextChangedListener
解决办法: 及时关闭资源
解决办法: 在在onDestory时,调用动画的cancel方法
解决办法: 参考Uber出品的一个开源库AutoDispose的使用,可以参考下文:
Android架构中添加AutoDispose解决RxJava内存泄漏
解决办法: 在销毁webview前一定要onDetachedFromWindow,我们先将webview从它的父view中移除再调用destroy方法
在 Android Lollipop 之前使用 AlertDialog 可能会导致内存泄漏
参考:一个内存泄漏引发的血案
Dialog和DialogFragment在Android5.0以下的内存泄漏
参考:解决Android5.0以下Dialog引起的内存泄漏
View的post方法导致的内存泄漏分析
view中有线程或者动画 要及时停止
这是为了防止内存泄漏,可以在onDetachedFromWindow方法中结束,这个方法回调的时机是 当View的Activity退出或者
当前View被移除的时候 会调用 这时候是结束动画或者线程的好时机 另外还有一个对应的方法 onAttachedToWindow 这
个方法调用的时机是在包含View的Activity启动时回调,回调在onDraw方法 之前
更少的空指针异常
更少的代码量
更快的开发速度
更一致的开发体验
一、深度集成“Project Treble”,更方便对安卓系统进行升级。
二、支持利用Wifi进行定位并且测量距离
三、可注册5个蓝牙音频设备并保存每台蓝牙设备的音量偏好
四、升级多任务界面功能,在多任务界面中可以对App进行操作:
五、加强了对刘海屏的支持
六、禁止从安卓系统的新版本刷回到老版本
Select * from table limit 19,11;
SELECT 'I''M '||'Chinese.'
熟悉linux操作系统基本命令优先
熟悉ROS(Robot Operating System)操作优先
有openGL开发经验
熟悉Linux环境下的开发
有车载系统相关研发经验者优先
有Android端渲染软件研发经验者优先
有语音应用开发经验优先考虑
如果对kotlin、RXjava,Flutter有使用和掌握的优先
有地图、LBS产品经验加分,熟悉C++语言加分
熟悉底层通信协议(USB、BT、WIFI等)、有相关驱动研发经验者优先