2021年7月最新中级Android面试题

目录

1.详细说明Activity生命周期

2.说明一下Android常用布局的特点

3.请说明一下Context 这个类的继承关系以及作用

4.Activity的四种LaunchMode

5.View的绘制流程

6.安卓多线程之间数据通信的方式

7.Handler的原理

8.两个Activity之间怎么传递数据?

9.简述TCP,UDP,Socket

10.Android中五种数据存储方式分别是什么?

11.进程和线程的区别

12.简要介绍关键字final和static的用法

13.数组和链表的区别。

14.ArrayList 和 LinkedList 的区别,以及应用场景。

15.a.hashcode() 有什么用,与 a.equals(b)有什么关系

16.在 jdk1.5 中,引入了泛型,泛型的存在是用来解决什么问题

17.Android性能优化

18.Thread和Runnable的区别

19.接口和抽象类的区别

20.Java中的Set、List、Map的区别


1.详细说明Activity生命周期

onCreate : 该方法是在Activity被创建时回调,它是生命周期第一个调用的方法,我们在创建Activity时一般都需要重写该方法,然后在该方法中做一些初始化的操作,如通过setContentView设置界面布局的资源,初始化所需要的组件信息等。 

onStart : 此方法被回调时表示Activity正在启动,此时Activity已处于可见状态,只是还没有在前台显示,因此无法与用户进行交互。可以简单理解为Activity已显示而我们无法看见摆了。 

onResume : 当此方法回调时,则说明Activity已在前台可见,可与用户交互了(处于前面所说的Active/Running形态),onResume方法与onStart的相同点是两者都表示Activity可见,只不过onStart回调时Activity还是后台无法与用户交互,而onResume则已显示在前台,可与用户交互。当然从流程图,我们也可以看出当Activity停止后(onPause方法和onStop方法被调用),重新回到前台时也会调用onResume方法,因此我们也可以在onResume方法中初始化一些资源,比如重新初始化在onPause或者onStop方法中释放的资源。 

onPause : 此方法被回调时则表示Activity正在停止(Paused形态),一般情况下onStop方法会紧接着被回调。但通过流程图我们还可以看到一种情况是onPause方法执行后直接执行了onResume方法,这属于比较极端的现象了,这可能是用户操作使当前Activity退居后台后又迅速地再回到到当前的Activity,此时onResume方法就会被回调。当然,在onPause方法中我们可以做一些数据存储或者动画停止或者资源回收的操作,但是不能太耗时,因为这可能会影响到新的Activity的显示——onPause方法执行完成后,新Activity的onResume方法才会被执行。 

onStop : 一般在onPause方法执行完成直接执行,表示Activity即将停止或者完全被覆盖(Stopped形态),此时Activity不可见,仅在后台运行。同样地,在onStop方法可以做一些资源释放的操作(不能太耗时)。 

onRestart :表示Activity正在重新启动,当Activity由不可见变为可见状态时,该方法被回调。这种情况一般是用户打开了一个新的Activity时,当前的Activity就会被暂停(onPause和onStop被执行了),接着又回到当前Activity页面时,onRestart方法就会被回调。 

onDestroy :此时Activity正在被销毁,也是生命周期最后一个执行的方法,一般我们可以在此方法中做一些回收工作和最终的资源释放。 

2.说明一下Android常用布局的特点

FrameLayout帧布局,显示特点:所有的子控件默认显示在FrameLayout的左上角,会重叠在一起显示。

LinearLayout线性布局,显示特点:所有子控件按照横向或者竖向依次排列。

RelativeLayout相对布局,显示特点:和LinearLayout布局相似,所有子控件默认显示在RelativeLayout的左上角。

GridLayout网格布局,显示特点:所有子控件默认在GridLayout中横向依次排列,当只等每行的列数时,到达指定列数 会自动换行显示。

TableLayout表格布局,表格布局和网格布局类似,但是需要注意的是,表格布局不能跨行,只能跨列。

3.请说明一下Context 这个类的继承关系以及作用

Context是应用程序环境中全局信息的接口,多被译为上下文,它整合了许多系统级的服务,可以用来获取应用中的类、资源,以及可以进行应用程序级的调起操作,比如启动Activity、Service等等,而且Context这个类是abstract的,不包含具体的函数实现。

Application、Activity都间接继承了Context

getApplication和getApplicationContext的区别

getApplication返回结果为Application,且不同的Activity和Service返回的Application均为同一个全局对象

getApplicationContext返回的也是Application对象,只不过返回类型为Context,看看它的实现

getContext 和 getActivity的区别

this:表示当前对象;一般而言,在哪个类中调用,就是指向该对象。

getContext():这个是View类中提供的方法,在继承了View的类中才可以调用,返回的是当前View运行在哪个Activity Context中。

getActivity():获得Fragment依附的Activity对象。Fragment里边的getActivity()不推荐使用原因如下:这个方法会返回当前Fragment所附加的Activity,当Fragment生命周期结束并销毁时,getActivity()返回的是null,所以在使用时要注意判断null或者捕获空指针异常。

4.Activity的四种LaunchMode

Standard:标准的启动模式,如果需要启动一个activity就会创建该activity的实例。也是activity的默认启动模式。

SingeTop:如果启动的activity已经位于栈顶,那么就不会重新创建一个新的activity实例。而是复用位于栈顶的activity实例对象。如果不位于栈顶仍旧会重新创建activity的实例对象。

SingleTask:设置了singleTask启动模式的activity在启动时,如果位于activity栈中,就会复用该activity,这样的话,在该实例之上的所有activity都依次进行出栈操作,即执行对应的onDestroy()方法,直到当前要启动的activity位于栈顶。一般应用在网页的图集,一键退出当前的应用程序。

singleInstance:如果使用singleInstance启动模式的activity在启动的时候会复用已经存在的activity实例。不管这个activity的实例是位于哪一个应用当中,都会共享已经启动的activity的实例对象。使用了singlestance的启动模式的activity会单独的开启一个共享栈,这个栈中只存在当前的activity实例对象。

5.View的绘制流程

View 绘制中主要流程分为measure,layout, draw 三个阶段。

measure :根据父 view 传递的 MeasureSpec 进行计算大小。

layout :根据 measure 子 View 所得到的布局大小和布局参数,将子View放在合适的位置上。

draw :把 View 对象绘制到屏幕上

6.安卓多线程之间数据通信的方式

1、handler
2、Activity.runOnUIThread(Runnable)
3、View.Post(Runnable)
4、View.PostDelayed(Runnabe,long)
5、AsyncTask

7.Handler的原理

Handler四大组件

                 1)Message

                       Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。

                       例:Message的what字段、arg1字段、arg2字段来携带整型数据,obj字段携带一个Object对象。

                 2)Handler

                       处理者,它主要用来发送和处理消息。发送消息一般是使用Handler的sendMessage()方法,消息经过处理后,最终传递到Handler的handlerMessage()方法中。

                 3)MessageQueue

                      消息队列,它主要用来存放所有通过Handler发送的消息,这部分消息会一直存在于消息队列中,等待被处理。

                      注意:每个线程中只会有一个MessageQueue对象。

                 4)Looper

                     是每个线程中MessageQueue的管家,调用Looper的loop()方法后,就会进入到一个无限循环当中,每当发现MessageQueue中存在一条消息,就会将其取出传递到Handler的handleMessage()方法当中。

                     注意:每个线程中只会有一个Looper对象。

8.两个Activity之间怎么传递数据?

Intent 可以启动一个Activity,也可以在启动Activity的时候传递数据。intent中提供了putExtra()方法,它可以把我们想要传递的数据暂存在intent中,启动了另一个Activity后,通过getIntent().getStringExtra()(其中getStringExtra()通过活动传递的数据类型决定是String或是其他类型),再从 Intent中取出。

9.简述TCP,UDP,Socket

TCP/IP即传输控制/网络协议,是面向连接的协议,发送数据前要先建立连接(发送方和接收方的成对的两个之间必须建 立连接),TCP提供可靠的服务,也就是说,通过TCP连接传输的数据不会丢失,没有重复,并且按顺序到达

UDP它是属于TCP/IP协议族中的一种。是无连接的协议,发送数据前不需要建立连接,是没有可靠性的协议。因为不需要建立连接所以可以在在网络上以任何可能的路径传输,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

socket连接就是所谓的长连接,客户端和服务器需要互相连接网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。

10.Android中五种数据存储方式分别是什么?

(1)SharedPreference,存放较少的五种类型的数据,只能在同一个包内使

            用,生成XML的格式存放在设备中

(2) SQLite数据库,存放各种数据,是一个轻量级的嵌入式数据库

(3) File文件,通过读取写入方式生成文件存放数据

(4) ContentProvider,主要用于让其他应用程序使用保存的数据

(5) 通过网络获取数据和写入数据到网络存储空间

11.进程和线程的区别

1.进程是资源分配最小单位,线程是程序执行的最小单位;

2.进程有自己独立的地址空间,每启动一个进程,系统都会为其分配地址空间,建立数据表来维护代码段、堆栈段和数据段,线程没有独立的地址空间,它使用相同的地址空间共享数据;

3.CPU切换一个线程比切换进程花费小;

4.创建一个线程比进程开销小;

5.线程占用的资源要⽐进程少很多。

6.线程之间通信更方便,同一个进程下,线程共享全局变量,静态变量等数据,进程之间的通信需要以通信的方式(IPC)进行;(但多线程程序处理好同步与互斥是个难点)

7.多进程程序更安全,生命力更强,一个进程死掉不会对另一个进程造成影响(源于有独立的地址空间),多线程程序更不易维护,一个线程死掉,整个进程就死掉了(因为共享地址空间);

8.进程对资源保护要求高,开销大,效率相对较低,线程资源保护要求不高,但开销小,效率高,可频繁切换;

12.简要介绍关键字final和static的用法

final 有着“终态的”“这是无法改变的”含义,阻止了多态和继承。

具体使用有:

final 类不能被继承,没有子类,final 类中的方法默认是 final 的。

final 方法不能被子类的方法覆盖,但可以被继承。

final 成员变量表示常量,只能被赋值一次,赋值后值不再改变。

final 不能用于修饰构造方法。

static 表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态 static 代

码块,但是 Java 语言中没有全局变量的概念。

 static 修饰的成员变量和成员方法独立于该类的任何对象,static 对象可以在它的任何对象创建之

前访问,无需引用任何对象。

static 前面也可用 public 或 private 来修饰,其中 private 是访问权限限定,static 表示不要实例化

就可以使用。

主要用于静态变量,静态方法,static 代码块

静态变量:对于静态变量在内存中只有一个拷贝(节省内存),JVM 只为静态分配一次内存,在加

载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但

是这是不推荐的)。

静态方法: 静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用 this

 super 关键字,不能直接访问所属类的实例变量和实例方法(就是不带 static 的成员变量和成员成

员方法),只能访问所属类的静态成员变量和成员方法。因为实例成员与特定的对象关联!

static 代码块:atic 代码块也叫静态代码块,是在类中独立于类成员的 static 语句块,可以有多个,

位置可以随便放,它不在任何的方法体内,JVM 加载类时会执行这些静态的代码块,如果 static 代

码块有多个,JVM 将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次

static 和 final 一起使用:

static final 用来修饰成员变量和成员方法,可简单理解为“全局常量”!

对于变量,表示一旦给值就不可修改,并且通过类名可以访问。

对于方法,表示不可覆盖,并且可以通过类名直接访问。

特别要注意一个问题:

对于被 static 和 final 修饰过的实例常量,实例本身不能再改变了,但对于一些容器类型(比如,

ArrayList、HashMap)的实例变量,不可以改变容器变量本身,但可以修改容器中存放的对象,这

一点在编程中用到很多。

13.数组和链表的区别。

数组:是将元素在内存中连续存储的;它的优点:因为数据是连续存储的,内存地址连续,所以在查找数据的时候效率比较高;它的缺点:在存储之前,我们需要申请一块连续的内存空间,并且在编译的时候就必须确定好它的空间的大小。在运行的时候空间的大小是无法随着你的需要进行增加和减少而改变的,当数据两比较大的时候,有可能会出现越界的情况,数据比较小的时候,又有可能会浪费掉内存空间。在改变数据个数时,增加、插入、删除数据效率比较低。

链表:是动态申请内存空间,不需要像数组需要提前申请好内存的大小,链表只需在用的时候申请就可以,根据需要来动态申请或者删除内存空间,对于数据增加和删除以及插入比数组灵活。还有就是链表中数据在内存中可以在任意的位置,通过应用来关联数据(就是通过存在元素的指针来联系)

14.ArrayList 和 LinkedList 的区别,以及应用场景。

ArrayList是基于数组实现的,ArrayList线程不安全。

LinkedList是基于双链表实现的:

使用场景:

1) 如果应用程序对各个索引位置的元素进行大量的存取或删除操作,ArrayList对象要远优于LinkedList对象;

2) 如果应用程序主要是对列表进行循环,并且循环时候进行插入或者删除操作,LinkedList对象要远优于ArrayList对象;

15.a.hashcode() 有什么用,与 a.equals(b)有什么关系

hashCode也是Object类的一个方法。返回一个离散的int型整数。在集合类操作中使用,为了提高查询速度。(HashMap,HashSet等比较是否为同一个)

如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等。

如果两个对象不equals,他们的hashcode有可能相等。

如果两个对象hashcode相等,他们不一定equals。

如果两个对象hashcode不相等,他们一定不equals。

16.在 jdk1.5 中,引入了泛型,泛型的存在是用来解决什么问题

泛型简单易用

类型安全 泛型的主要目标是实现java的类型安全。 泛型可以使编译器知道一个对象的限定类型是什么,这样编译器就可以在一个高的程度上验证这个类型

消除了强制类型转换 使得代码可读性好,减少了很多出错的机会

Java语言引入泛型的好处是安全简单。泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

17.Android性能优化

1.布局优化

减少嵌套的层级(可使用约束布局),减少嵌套层级可加快加载效率,

使用style提取相同view的公共属性,减少重复代码

使用include标签
2.图片的优化

android中图片的使用是非常占用内存资源的。

①:在图片未使用时,及时recycle()回收

②:使用三级缓存,内存-sd卡-网络

内存中再次获取最快,由于内存有限可能被gc回收,sd卡中的图片不会回收,当前面两种都不存在所需图片时,才去网洛下载

③:将大图片进行压缩处理再放到内存中,用到BitmapFactory类
3.大量数据优化

分页加载

缓存方式

列表项优化

listview的优化

convertview的复用(View的复用)

viewholder类的使用,减少查找控件的次数(findviewbyid()次数),将holder与view绑定来实现(.setTag()、.getTag())

数据分页加载

RecycleView的优化

18.Thread和Runnable的区别

1) 如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
2) Runnable 是接口。Thread 是类,且实现了Runnable接口。
3) 实现Runnable接口相比继承Thread类有如下好处:避免继承的局限,一个类可以实现多个接口。

19.接口和抽象类的区别

抽象类和接口分别给出了不同的语法定义(包括方法体、成员变量修饰符、方法修饰符)

抽象是对类的抽象,接口是对行为的抽象

抽象所体现的是继承关系,是一种”is-a”的关系,接口仅仅实现接口定义的契约,是一种”like-a”的关系

抽象是自底向上抽象的,接口是自顶向下设计出来的

20.Java中的Set、List、Map的区别

Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。 Set接口主要实现了两个实现类:HashSet: HashSet类按照哈希算法来存取集合中的对象,存取速度比较快

TreeSet :TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序。

List的特征是其元素以线性方式存储,集合中可以存放重复对象。

ArrayList() : 代表长度可以改变得数组。可以对元素进行随机的访问,向ArrayList()中插入与删除元素的速度慢。

LinkedList(): 在实现中采用链表数据结构。插入和删除速度快,访问速度慢。

Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。 Map没有继承于Collection接口 从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。

HashMap:Map基于散列表的实现。插入和查询“键值对”的开销是固定的。可以通过构造器设置容量capacity和负载因子load factor,以调整容器的性能。

LinkedHashMap: 类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时发而更快,因为它使用链表维护内部次序。

TreeMap : 基于红黑树数据结构的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在 于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。

WeakHashMao :弱键(weak key)Map,Map中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收。

猜你喜欢

转载自blog.csdn.net/qq_17798399/article/details/118485843