Android面试题2

版权声明:个人见解,希望可以帮助大家,共同进步. https://blog.csdn.net/weixin_40783315/article/details/83783839

20.图片的异步加载的方法?

1.利用软引用来缓存图片Bitmap,用图片的URL作为缓存查找的Key 
2.设两级缓存,一级是SoftReference,二级是本地SD卡; 
3.如果两级缓存都没取到图片,则从服务器获取,并加入缓存; 
4.加载完后通过回调接口通知UI更新; 

瀑布流实现方式?

1)自定义scrollView,动态代码添加LinearLayout及ImageView

      a.自定义scrollView,并且使用监听器模式,对其滚动到最顶部、及最底部进行监听操作。

      b.在Activity里对scrollView的横向的LinearLayout动态添加列数,每一列是一个竖向的linearLayout.

      c.根据列数以及list.size()对每一列的linearLayout添加ImageView.

      d.根据监听器对其滚动到顶部(不做操作)、滚到最底部(加载更多数据)、正在滚动进行操作(滚动超过两屏,回收两屏之前图片回收及回滚到之前屏幕图片重载)。

把一张特别大的图片,分成几十张小的图片,在最短的时间内给处理?

http://www.linuxidc.com/Linux/2012-11/73939p2.htm

方法1:如果你将return-data设置为“true”,你将会获得一个与内部数据关联的Action,并且bitmap以此方式返回:(Bitmap)extras.getParcelable("data")。注意:如果你最终要获取的图片非常大,那么此方法会给你带来麻烦,所以你要控制outputX和outputY保持在较小的尺寸。鉴于此原因,在我的代码中没有使用此方法((Bitmap)extras.getParcelable("data"))。
方法2: 如果你将return-data设置为“false”,那么在onActivityResult的Intent数据中你将不会接收到任何Bitmap,相反,你需要将MediaStore.EXTRA_OUTPUT关联到一个Uri,此Uri是用来存放Bitmap的。但是还有一些条件,首先你需要有一个短暂的与此Uri相关联的文件地址,当然这不是个大问题(除非是那些没有sdcard的设备)。

 

Android dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念?

DVM指dalivk的虚拟机。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。而每一个DVM进程都是在Linux系统中的一个进程,所以可以认为是同一个概念。 

Dalvik和Java运行环境的区别  [
1:Dalvik主要是完成对象生命周期管理,堆栈管理,线程管理,安全和异常管理,以及垃圾回收等等重要功能。
2:Dalvik负责进程隔离和线程管理,每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。   
3:不同于Java虚拟机运行java字节码,Dalvik虚拟机运行的是其专有的文件格式Dex 4:dex文件格式可以减少整体文件尺寸,提高I/o操作的类查找速度。   
5:odex是为了在运行过程中进一步提高性能,对dex文件的进一步优化。   
6:所有的Android应用的线程都对应一个Linux线程,虚拟机因而可以更多的依赖操作系统线程调度管理机制 
7:有一个特殊的虚拟机进程Zygote,他是虚拟机实例的孵化器。它在系统启动的时候就会产生,它会完成虚拟机的初始化,库的加载,预制类库和初始化的操作。如果系统需要一个新的虚拟机实例,它会迅速复制自身,以最快的数据提供给系统。对于一些只读的系统库,所有虚拟机实例都和Zygote共享一块内存区域。

  1. 嵌入式操作系统内存管理有哪几种,各有何特性 ?

 1、虚拟内存管理机制: 有一些嵌入式处理器提供了MMU,在MMU具备内存地址映射和寻址功能,它使操作系统的内存管理更加方便。如果存在MMU ,操作系统会使用它完成从虚拟地址到物理地址的转换, 所有的应用程序只需要使用虚拟地址寻址数据。 这种使用虚拟地址寻址整个系统的主存和辅存的方式在现代操作系统中被称为虚拟内存。MMU 便是实现虚拟内存的必要条件。 虚拟内存的管理方法使系统既可以运行体积比物理内存还要大的应用程序,也可以实现“按需调页”策略,既满足了程序的运行速度,又节约了物理内存空间。 在L inux系统中,虚拟内存机制的实现实现为我们提供了一个典型的例子:在不同的体系结构下, 使用了三级或者两级页式管理,利用MMU 完成从虚拟地址到物理地址之间的转换。基于虚拟内存管理的内存最大好处是:由于不同进程有自己单独的进程空间,十分有效的提高了系统可靠性和安全性。 2、非虚拟内存管理机制: 在实时性要求比较高的情况下,很多嵌入式系统并不需要虚拟内存机制:因为虚拟内存机制会导致不确定性的 I/O阻塞时间, 使得程序运行时间不可预期,这是实时嵌入式系统的致命缺陷;另外,从嵌入式处理器的成本考虑,大多采用不装配MMU 的嵌入式微处理器。所以大多嵌入式系统采用的是实存储器管理策略。因而对于内存的访问是直接的,它对地址的访问不需要经过MMU,而是直接送到地址线上输出,所有程序中访问的地址都是实际的物理地址;而且,大多数嵌入式操作系统对内存空间没有保护,各个进程实际上共享一个运行空间。一个进程在执行前,系统必须为它分配足够的连续地址空间,然后全部载入主存储器的连续空间。

 

  1. 什么是嵌入式实时操作系统, Android 操作系统属于实时操作系统吗?

嵌入式实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统
    嵌入式操作系统主要用于工业控制、军事设备、航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。又可分为软实时和硬实时两种,而 android 是基于 linux 内核的,因此属于软实时。

26.一条最长的短信息约占多少byte? 

一条最长的短信息约占140byte

 

  1. android中的动画有哪几类,它们的特点和区别是什么?

答:Android中动画可以分为两大类:帧动画、补间动画

1)补间动画:(你定义一个开始和结束,中间的部分由程序运算得到。就是对场景里的对象不断的进行图像变化来产生动画效果(旋转、平移、放缩和渐变))AlphaAnimation(渐变型动画)、scaleAnimation(缩放型动画)、 TranslateAnimation(平移型动画)、 RotateAnimation(旋转型动画)、

2)逐帧动画:Frame(把一连串的图片进行系列化连续播放,如同放电影的效果),它是通过播放一张一张图片来达到动画的效果;

28.handler机制的原理,looper通过什么方法开始的?

一个Handler允许你发送和处理Message和Runable对象,每个线程都有自己的Looper,每个Looper中封装着MessageQueue。Looper负责不断的从自己的消息队列里取出队头的任务或消息执行。每个handler也和线程关联,Handler负责把Message和Runable对象传递给MessageQueue(用到post ,sendMessage等方法),而且在这些对象离开MessageQueue时,Handler负责执行他们(用到handleMessage方法)。

其中Message类就是定义了一个信息,这个信息中包含一个描述符和任意的数据对象,这个信息被用来传递给Handler.Message对象提供额外的两个int域和一个Object域。

默认情况下一个线程是不存在消息循环(message loop)的,需要调用Looper.prepare()来给线程创建一个消息循环,调用Looper.loop()来使消息循环起作用,从消息队列里取消息,处理消息。调用Looper.loop()之后循环已经开始,下一个由handler发的message将会被这个handler的handleMessage方法处理,这是一个----循环。

Looper从MessageQueue中取出Message之后,交由Handler的handleMessage进行处理。处理完成后,调用Message.recycle()将其放入Message Pool中。

29.说说mvc模式的原理,在android中的运用?

答:mvc是model,view,controller的缩写,mvc包含三个部分:
  模型(model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该层。
  视图(view)对象:是应用程序中负责生成用户界面的部分。也是在整个mvc架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。
  控制器(control)对象:是根据用户的输入,控制用户界面数据显示及更新model对象状态的部分,控制器更重要的一种导航功能,响应用户出发的相关事件,交给m层处理。
android鼓励弱耦合和组件的重用,在android中mvc的具体体现如下:
1)视图层(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入,当然,如果你对android了解的比较的多了话,就一定可以想到在android中也可以使用javascript+html等的方式作为view层,当然这里需要进行java和javascript之间的通信,幸运的是,android提供了它们之间非常方便的通信实现。
2)控制层(controller):android的控制层的重任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写代码,要通过activity交割model业务逻辑层处理,这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。

 

30.如何让Activity变成一个窗口?

答:在清单文件AndroidManifest.xml中相应的<activity>标签内设置属性android:theme=”@android:style/Theme.Dialog”

 

31.后台的Activity被系统回收怎么办?

除了在栈顶的Activity,其他的Activity都有可能在内存不足的时候被系统回收,一个Activity越处于栈底,被回收的可能性就越大。如果我们没有覆写onSaveInstanceState()方法,此方法的默认实现会自动保存Activity中的某些状态数据,比如Activity中各种UI空间的状态。Android应用框架中定义的几乎所有的UI控件都恰当的实现了onSaveInstanceState()方法,因此当Activity被摧毁和重建时,这些UI控件会自动保存和恢复状态数据。比如EditText控件会自动保存和恢复输入的数据,而CheckBox控件会自动保存和恢复选中状态。开发者只需要为这些控件指定一个唯一的ID(通过设置android:id属性即可),剩余的事情就可以自动完成了。如果没有为控件指定ID,则这个控件就不会进行自动的数据保存和恢复操作。
由上所述,如果我们需要覆写onSaveInstanceState()方法,一般会在第一行代码中调用该方法的默认实现:super.onSaveInstanceState(outState)。

32.ListView优化?

答:1)、对convetView进行判空,是当convertView不为空的时候直接重新使用convertView

从而减少了很多不必要的View的创建

2)定义一个ViewHolder,将convetView的tag设置为ViewHolder,不为空时重新使用即可

3)、当ListView加载数据量较大时可以采用分页加载和图片异步加载

 

33.IPC及其原理?

 

1).Binder通信是如何实现的?

   1.Binder通信是通过linux的binder driver来实现的,

   2.Binder通信操作类似线程迁移(thread migration),两个进程间IPC看起来就象是一个进程进入另一个进程执行代码然后带着执行的结果返回;

1)IPC(Inter-Process Communication,进程间通信),

aidl是 Android Interface definition language的缩写,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口.编译器可以通过扩展名为aidl的文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的.

BroadcastReceiver也可以实现进程间通信

ContentProvider 提供进程间数据共享 

2).Android的 Service工作流程

  1.Android虚拟机启动之前系统会先启动service Manager进程;

  2.service Manager打开binder驱动,并通知binder kernel驱动程序这个进程将作为System Service Manager;

  3.然后该进程将进入一个循环,等待处理来自其他进程的数据。

  4.用户创建一个System service后,通过defaultServiceManager得到一个远程ServiceManager的接口,通过这个接口我们可以调用addService函数将System service添加到Service Manager进程中;

  5.然后client可以通过getService获取到需要连接的目的Service的IBinder对象,这个IBinder是Service的BBinder在binder kernel的一个参考,

  6.所以service IBinder 在binder kernel中不会存在相同的两个IBinder对象,每一个Client进程同样需要打开Binder驱动程序。对用户程序而言,我们获得这个对象就可以通过binder kernel访问service对象中的方法。

  7.Client与Service在不同的进程中,通过这种方式实现了类似线程间的迁移的通信方式,对用户程序而言当调用Service返回的IBinder接口后,访问Service中的方法就如同调用自己的函数。

34.View如何刷新?

安卓要更新界面不要在主线程中去做

如果是在线程thread中获取到了新的数据,需要配合使用hanlder进行刷新.

在线程中刷新View用postinvalidate();

在UI线程中刷新View的方法是invalidate()函数,

当调用线程处于空闲状态时,调onDraw()刷新界面

 

如果是listView刷新数据,用adapter.notifyDataSetInvalidated();

adapter.notifyDataSetChanged();

35.DDMS与TraceView的区别?

DDMS是一个程序执行查看器,在里面可以看见线程和堆栈等信息,TraceView是程序性能分析器 。

36.在Java中如何引入C语言?


java中利用JNI引用本地语言 (java native interface  java 本地接口)接口 。
1.在应用程序中定义本地接口(native)编译成.h头文件,交由C程序员实现,将.c实现通过NDk编译成.so动态链接库(windows下是.dll, linux下是.so,导入项目中的libs/armeabi,代码中调用本地接口,
应用场景:音频,拍摄车牌号

37.链表和数组的区别?

数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。

链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。比如:上一个元素有个指针指到下一个元素,以此类推,直到最后一个元素。如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表数据结构了。

二者都属于一种数据结构
(1) 从逻辑结构角度来看
  a, 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。
  b,链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项)
(2)从内存存储角度来看
  a,(静态)数组从栈中分配空间, 对于程序员方便快速,但自由度小。
  b, 链表从堆中分配空间, 自由度大但申请管理比较麻烦.

  1. Hash表是什么?有什么用?

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数

作用:HASH表主要就是提供更快的查找速度,简单来说就是分桶。 

比如说你们学校的一个年级有很多班是吧? 那么现在要查找一位同学。如果不看班级直接找,就需要每个班级一个一个的查找是不? 那现在因为分了班级,我们有一个函数可以通过名字产生它的班级号。比如说王勇,二班。 那么现在我们直接hash( 王勇) = 2; 然后我们就直接从2班开始找。 如果2班有50个学生,那么我们最多查找50次对吗? 好。假设你们年级一共有10个班,如果没有这个hash函数,那么直接找,最坏可能要查找50*10=500次。!! 这个班级其实就是每个桶!! 这就是分桶。。。通过哈希函数产生哈希值,然后相同哈希值的元素放在相同的桶里边。。。! 

这样可以通过hash这个间接作用减少查找的时间和次数!这就是它的意义!!

  1. 什么是锁?有什么用?有哪些锁?为什么需要锁?

锁是为了保证安全性,如程序运行时保证另外的程序不能再对本程序所使用到的数据进行某些操作,版本软件的“不能合并”文件不能同时被两人修改等。

锁分为:线程锁,数据库锁,SVN锁等等

  1、当几个线程都用到了某个量,但是这个量却能影响程序的运行时就需要线程锁来控制一次只能由一个线程访问这个量。如果没有使用线程锁会出现争用情况。

两个或更多的线程或进程读或写一些共享数据,而最终结果取决于这些线程是如何被调度计时的。争用情况可能会导致不可预见的结果和隐蔽的程序错误。 

2、数据库锁的作用是防止程序运行的时候其他的程序不能再对该程序所使用到的数据进行操作,保护数据的安全性。

 3、SVN锁的作用是防止版本软件中的“不能合并”的文件(如:图形文件)不能被多人同时更改的时候进行锁定,当一个人对其进行操作时,其他人不能对这个文件再进行操作,保证了文件的安全性。

猜你喜欢

转载自blog.csdn.net/weixin_40783315/article/details/83783839
今日推荐