android 基础

  • dp是什么,sp呢,有什么区别

    Density-independent pixel (dp)独立像素密度。标准是160dip.即1dp对应1个pixel,,屏幕密度越大,1dp对应 的像素点越多。 上面的公式中有个dpi,dpi为DPI是Dots Per Inch(每英寸所打印的点数),也就是当设备的dpi为160的时候1px=1dp

sp和dp很类似但唯一的区别是,Android系统允许用户自定义文字尺寸大小(小、正常、大、超大等等),当文字尺寸是“正常”时1sp=1dp=0.00625英寸,而当文字尺寸是“大”或“超大”时,1sp>1dp=0.00625英寸。类似我们在windows里调整字体尺寸以后的效果——窗口大小不变,只有文字大小改变
  • 自定义View,ViewGroup注意那些回调?

    有自定义view 和 自定义 viewGroup 注意的方法就是onMeasure onLayout onDraw ,自定义view 一般需要重写onDraw 而自定义viewgroup 必须重写 onlayout 方法

  • 界面卡顿的原因以及解决方法
    Android每个16ms就会绘制一次Activity,通过上述的结论我们知道,如果由于一些原因导致了我们的逻辑、CPU耗时、GPU耗时大于16ms,UI就无法完成一次绘制,那么就会造成卡顿。简单的一句话就是:卡主线程了。

    解决方法:
    1. 优化一些耗时的方法,将耗时的动作放到子线程中,例如网络访问,大文件的读写,防止anr
    2. 布局尽量简化,防止过度绘制

  • android中的存储类型

    ① 使用SharedPreferences存储数据 

    ② 文件存储数据

    ③  SQLite数据库存储数据

    ④ 使用ContentProvider存储数据

    ⑤ 网络存储数据 

  • service用过么,基本调用方法

    1. 启动状态
         当应用组件(如 Activity)通过调用 startService() 启动服务时,服务即处于“启动”状态。一旦启动,服务即可在后台无限期运行,即使启动服务的组件已被销毁也不受影响,除非手动调用才能停止服务, 已启动的服务通常是执行单一操作,而且不会将结果返回给调用方。

    2. 绑定状态
         当应用组件通过调用 bindService() 绑定到服务时,服务即处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。 仅当与另一个应用组件绑定时,绑定服务才会运行。 多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。

  • 服务Service与线程Thread的区别

    两者概念的迥异

    Thread 是程序执行的最小单元,它是分配CPU的基本单位,android系统中UI线程也是线程的一种,当然Thread还可以用于执行一些耗时异步的操作。

    Service是Android的一种机制,服务是运行在主线程上的,它是由系统进程托管。它与其他组件之间的通信类似于client和server,是一种轻量级的IPC通信,这种通信的载体是binder,它是在linux层交换信息的一种IPC,而所谓的Service后台任务只不过是指没有UI的组件罢了。

    两者的执行任务迥异

    在android系统中,线程一般指的是工作线程(即后台线程),而主线程是一种特殊的工作线程,它负责将事件分派给相应的用户界面小工具,如绘图事件及事件响应,因此为了保证应用 UI 的响应能力主线程上不可执行耗时操作。如果执行的操作不能很快完成,则应确保它们在单独的工作线程执行。

    Service 则是android系统中的组件,一般情况下它运行于主线程中,因此在Service中是不可以执行耗时操作的,否则系统会报ANR异常,之所以称Service为后台服务,大部分原因是它本身没有UI,用户无法感知(当然也可以利用某些手段让用户知道),但如果需要让Service执行耗时任务,可在Service中开启单独线程去执行。

    两者使用场景

    当要执行耗时的网络或者数据库查询以及其他阻塞UI线程或密集使用CPU的任务时,都应该使用工作线程(Thread),这样才能保证UI线程不被占用而影响用户体验。

    在应用程序中,如果需要长时间的在后台运行,而且不需要交互的情况下,使用服务。比如播放音乐,通过Service+Notification方式在后台执行同时在通知栏显示着。

    两者的最佳使用方式

    在大部分情况下,Thread和Service都会结合着使用,比如下载文件,一般会通过Service在后台执行+Notification在通知栏显示+Thread异步下载,再如应用程序会维持一个Service来从网络中获取推送服务。在Android官方看来也是如此,所以官网提供了一个Thread与Service的结合来方便我们执行后台耗时任务,它就是IntentService,(如果想更深入了解IntentService,可以看博主的另一篇文章:Android 多线程之IntentService 完全详解),当然 IntentService并不适用于所有的场景,但它的优点是使用方便、代码简洁,不需要我们创建Service实例并同时也创建线程,某些场景下还是非常赞的!由于IntentService是单个worker thread,所以任务需要排队,因此不适合大多数的多任务情况。

  • Handler机制

    首先,是这个MessageQueen,MessageQueen是一个消息队列,它可以存储Handler发送过来的消息,其内部提供了进队和出队的方法来管理这个消息队列,其出队和进队的原理是采用单链表的数据结构进行插入和删除的,即enqueueMessage()方法和next()方法。这里提到的Message,其实就是一个Bean对象,里面的属性用来记录Message的各种信息。

    然后,是这个Looper,Looper是一个循环器,它可以循环的取出MessageQueen中的Message,其内部提供了Looper的初始化和循环出去Message的方法,即prepare()方法和loop()方法。在prepare()方法中,Looper会关联一个MessageQueen,而且将Looper存进一个ThreadLocal中,在loop()方法中,通过ThreadLocal取出Looper,使用MessageQueen的next()方法取出Message后,判断Message是否为空,如果是则Looper阻塞,如果不是,则通过dispatchMessage()方法分发该Message到Handler中,而Handler执行handlerMessage()方法,由于handlerMessage()方法是个空方法,这也是为什么需要在Handler中重写handlerMessage()方法的原因。这里要注意的是Looper只能在一个线程中只能存在一个。这里提到的ThreadLocal,其实就是一个对象,用来在不同线程中存放对应线程的Looper。

    最后,是这个Handler,Handler是Looper和MessageQueen的桥梁,Handler内部提供了发送Message的一系列方法,最终会通过MessageQueen的enqueueMessage()方法将Message存进MessageQueen中。我们平时可以直接在主线程中使用Handler,那是因为在应用程序启动时,在入口的main方法中已经默认为我们创建好了Looper。

  • LinearLayout、FrameLayout、RelativeLayout性能对比,为什么?
    1.RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,也会调用子View2次onMeasure

    2.RelativeLayout的子View如果高度和RelativeLayout不同,则会引发效率问题,当子View很复杂时,这个问题会更加严重。如果可以,尽量使用padding代替margin。

    3.在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout。
    最后再思考一下文章开头那个矛盾的问题,为什么Google给开发者默认新建了个RelativeLayout,而自己却在DecorView中用了个LinearLayout。因为DecorView的层级深度是已知而且固定的,上面一个标题栏,下面一个内容栏。采用RelativeLayout并不会降低层级深度,所以此时在根节点上用LinearLayout是效率最高的。而之所以给开发者默认新建了个RelativeLayout是希望开发者能采用尽量少的View层级来表达布局以实现性能最优,因为复杂的View嵌套对性能的影响会更大一些。

    4.能用两层LinearLayout,尽量用一个RelativeLayout,在时间上此时RelativeLayout耗时更小。另外LinearLayout慎用layout_weight,也将会增加一倍耗时操作。由于使用LinearLayout的layout_weight,大多数时间是不一样的,这会降低测量的速度。这只是一个如何合理使用Layout的案例,必要的时候,你要小心考虑是否用layout weight。总之减少层级结构,才是王道,让onMeasure做延迟加载,用viewStub,include等一些技巧。

  • Activity的生命周期,finish调用后其他生命周期还会走么?

    1. 在onCreate方法中调用finish,不会显示出此Activity的界面,因为调用finish方法后,立马就会跑onDestroy。即跑的生命周期为:onCreate、onDestroy。

    2. 在onStart方法中调用finish,会出现闪退,因为调用finish方法后,立马就会跑onStop方法。即跑的生命周期为:onCreate、onStart、onStop、onDestroy。

    3. 在onResume方法中调用finish,会出现闪退,因为调用finish方法后,立马就会跑onStop方法。即跑的生命周期为:onCreate、onStart、onResume、onPause、onStop、onDestroy。

    4. 在onPause、onStop、onDestroy中,调用finish,显示正常。在退出时,正常退出。跑的生命周期为:onCreate、onStart、onResume、onPause、onStop、onDestroy。

  • framework层熟悉么,源码了解

    Framework是android 系统对 linux kernel,lib库等封装,提供WMS(),AMS(ActivityManagerService),bind机制,handler-message机制等方式,供app使用。

    简单来说framework就是提供app生存的环境。

    1)Activity在attch方法的时候,会创建一个phonewindow(window的子类)

    2)onCreate中的setContentView方法,会创建DecorView

    3)DecorView 的addview方法,会把layout中的布局加载进来。

  • GC回收机制熟悉么,分代算法知道么

    1.标记清除

    也就是每次GC,会先扫描内存区标记存活对象,而后释放未被标记的对象空间。这种算法在工作时需要停止工作线程,再进行标记清除,同时会产生内存碎片,而且jvm需要维护一个内存空间表,用于分配内存空间。

    2.复制清除

    将内存区分为两个相同大小的区域,先在A上分配对象,当其分配满后,进行标记操作,而后将标记对象按照内存顺序复制到B区域中,最后将A区域全部清除。这种方式可以有效避免内存碎片的问题,但是复制操作会产生额外的耗时,当存活对象多时并不适合使用该算法,因为复制所产生的耗时会很长。因此这种算法适合对象存活时间短的情况。同时会造成一定的内存浪费。

    3.标记整理

    这种算法就是在标记清除的基础上为了避免内存碎片的产生而优化产生的算法。总的过程分为两步,分别是标记和整理。

    java内存模型将内存区域分为,新生代、老年代、永久代。
    新生代由于其对象存活时间短,且需要经常gc,因此采用效率较高的复制算法,其将内存区分为一个eden区和两个suvivor区,eden区和survivor区的比例是8:1,分配内存时先分配eden区,当eden区满时,使用复制算法进行gc,将存活对象复制到一个survivor区,当一个survivor区满时,将其存活对象复制到另一个区中,当对象存活时间大于某一阈值时,将其放入老年代。

  • Java的类加载原理

    引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。

    扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。

    系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。

    双亲委派模型:

    某一个类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,则成功返回;如果父类加载器无法完成加载任务,将抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载,依次类推。

  • 内存泄漏如何排查,MAT分析方法以及原理,各种泄漏的原因是什么比如

    什么时候会发生内存泄露?内存泄露的根本原因:长生命周期的对象持有短生命周期的对象。短周期对象就无法及时释放。

    I. 静态集合类引起内存泄露
    主要是hashmap,Vector等,如果是静态集合 这些集合没有及时setnull的话,就会一直持有这些对象。

    II.remove 方法无法删除set集 Objects.hash(firstName, lastName);
    经过测试,hashcode修改后,就没有办法remove了。

    III. observer 我们在使用监听器的时候,往往是addxxxlistener,但是当我们不需要的时候,忘记removexxxlistener,就容易内存leak。
    广播没有unregisterrecevier

    IV.各种数据链接没有关闭,数据库contentprovider,io,sokect等。cursor

    V.内部类:
    java中的内部类(匿名内部类),会持有宿主类的强引用this。
    所以如果是new Thread这种,后台线程的操作,当线程没有执行结束时,activity不会被回收。
    Context的引用,当TextView 等等都会持有上下文的引用。如果有static drawable,就会导致该内存无法释放。

    VI.单例
    单例 是一个全局的静态对象,当持有某个复制的类A是,A无法被释放,内存leak。

  • Handler为什么会泄漏

    1. 定义静态handler 对activity 进行弱引用

      我们定义的handler对象其实是一个内部匿名了它会隐式的持有外部类的引用,解决方法就是使用静态变量定义handler,由于handler 静态变量就无法引用外部的activity 对象了,增加一个对activity 的弱引用.

    2. 在activity 的onDestory方法中判断handler 是否执行完成,进行相关操作.

  • 热修复了解么,用的什么?

  • apk包大小有限制么?怎么减少包大小?

  • 工作中有没有用过或者写过什么工具?脚本,插件等等

  • 比如:多人协同开发可能对一些相同资源都各自放了一份,有没有方法自动检测这种重复之类的

  • 写过native的底层代码么

  • anr是因为什么产生的,怎么排查

    ANR的关键
    是处理超时,所以应该避免在UI线程,BroadcastReceiver 还有service主线程中,处理复杂的逻辑和计算而交给work thread操作。
    1)避免在activity里面做耗时操作,oncreate & onresume
    2)避免在onReceiver里面做过多操作
    3)避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。
    4)尽量使用handler来处理UI thread & workthread的交互。

  • 平时用过哪些设计模式?

    单例、工厂、观察者、代理

    单例模式:目的是为了让系统中只有一个调用对象,缺点是单例使其他程序过分依赖它,而且不同单例运行在不同进程中,使得维护困难;

    工厂模式:生产固定的一些东西,如抽象类,缺点是产品修改麻烦;

    观察者模式:就是多个对象对一个对象进行监控,如缓存;

    代理模式:自己的事交给别人去做,分别返回结果即可,如异步线程;

    建造者模式:AlertDialog.Builder retrofit

  • savedInstanceState知道么,干什么用的,什么时候有值,什么时候为空,平时是怎么用的

    当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。

  • 热修复原理

    Android的类加载器分为两种,PathClassLoader和DexClassLoader,两者都继承自BaseDexClassLoader

    PathClassLoader 用来加载系统类和应用类

    DexClassLoader 用来加载jar、apk、dex文件.加载jar、apk也是最终抽取里面的Dex文件进行加载.

  • View绘制熟悉么,介绍下,能说下是实现原理么?

    Android应用程序的显示过程包含了两个部分(应用侧绘制、系统侧渲染)、两个机制(进程间通讯机制、显示刷新机制)

    双缓冲意味着要使用两个缓冲区(SharedBufferStack中),其中一个称为Front Buffer,另外一个称为Back Buffer。UI总是先在Back Buffer中绘制,然后再和Front Buffer交换,渲染到显示设备中。理想情况下,这样一个刷新会在16ms内完成(60FPS),下图就是描述的这样一个刷新过程(Display处理前Front Buffer,CPU、GPU处理Back Buffer。

  • 有什么工具可以看到Activity栈信息么?多个栈话,有方法分别得到各个栈的Activity列表么

  • 都熟悉哪些命令?知道怎么用命令启动一个Activity么?

  • SharedPrefrences的apply和commit有什么区别

  • java里带$的函数见过么,是什么意思

  • MD5是加密方法么,Base64呢

  • android 8.0 有哪些新特性

  • glide缓存策略?同一个图片跟size有关么

  • android中的动画有哪些

  • Fragment的replace和end??的区别?

  • MVP,MVVM,MVC解释和实践

  • 微信跳一跳外挂怎么实现,检测怎么做的?

  • 一张纯色背景下怎么有效检测各个矩形?

  • 对接的so算法了解么,有接触过相关的库么?

  • android api层的源码熟悉哪些?解释一下

  • 怎么处理嵌套View的滑动冲突问题

  • 热修复相关的原理,框架熟悉么

  • gradle打包流程熟悉么

  • Canvas的底层机制,绘制框架,硬件加速是什么原理,canvas lock的缓冲区是怎么回事

  • surfaceview, suface,surfacetexure等相关的,以及底层原理

  • android文件存储,各版本存储位置的权限控制的演进,外部存储,内部存储

  • 上层业务activity和fragment的遇到什么坑??页面展示上的一些坑和优化经验

  • 网络请求的开源框架:OKHttp介绍,写过拦截器么

  • 数据层有统一的管理么,数据缓存是怎么做的,http请求等有提供统一管理么?

  • 有用什么模式么,逻辑什么的都在Activity层?怎么分离的

  • 如果用了一些解耦的策略,怎么管理生命周期的?

  • 有什么提高编译速度的方法?

  • 对应用里的线程有做统一管理么?

  • jni的算法提供都是主线程的?是不是想问服务类的啊

  • 边沿检测用的啥?深度学习相关的有了解么?

  • 上线后的app性能分析检测有做么

  • 进程间通信方式?Binder的构成有几部分?

  • HttpClient和HttpConnection的区别

  • View的事件传递机制

  • MVC,MVP,MVVM分别是什么?

  • 内存优化,OOM的原因和排查方法

    当程序需要申请一段“大”内存,但是虚拟机没有办法及时的给到,即使做了GC操作以后

    减少内存对象的占用

    I.ArrayMap/SparseArray代替hashmap

    II.避免在android里面使用Enum

    III.减少bitmap的内存占用

    inSampleSize:缩放比例,在把图片载入内存之前,我们需要先计算出一个合适的缩放比例,避免不必要的大图载入。

    decode format:解码格式,选择ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,存在很大差异。

    IV.减少资源图片的大小,过大的图片可以考虑分段加载

    内存对象的重复利用
    大多数对象的复用,都是利用对象池的技术。
    I.listview/gridview/recycleview contentview的复用

    II.inBitmap 属性对于内存对象的复用ARGB_8888/RBG_565/ARGB_4444/ALPHA_8这个方法在某些条件下非常有用,比如要加载上千张图片的时候。

    III.避免在ondraw方法里面 new对象

    IV.StringBuilder 代替+

  • 想改变listview的高度,怎么做

  • Https是怎么回事?

  • 除了日常开发,其他有做过什么工作?比如持续化集成,自动化测试等等

  • ActivityA跳转ActivityB然后B按back返回A,各自的生命周期顺序,A与B均不透明。

  • Synchronize关键字后面跟类或者对象有什么不同。

  • 单例的DCL方式下,那个单例的私有变量要不要加volatile关键字,这个关键字有什么用

  • JVM的引用树,什么变量能作为GCRoot?GC垃圾回收的几种方法

  • ThreadLocal是什么?Looper中的消息死循环为什么没有ANR?

  • Android中main方法入口在哪里

  • jdk1.5?SparseArray和ArrayMap各自的数据结构,前者的查找是怎么

  • 实现的,与HashMap的区别

  • Runnable与Callable、Future、FutureTask的区别,AsyncTask用到哪个?AsyncTask是顺序执行么,for循环中执行200次new AsyncTask并execute,会有异常吗

  • IntentService生命周期是怎样的,使用场合等

  • RecyclerView和ListView有什么区别?局部刷新?前者使用时多重type场景下怎么避免滑动卡顿。懒加载怎么实现,怎么优化滑动体验。

  • SQLite的数据库升级用过么

  • 开放问题:如果提高启动速度,设计一个延迟加载框架或者sdk的方法和注意的问题。

  • Scroller有什么方法,怎么使用的。

  • 分享下项目中遇到的问题

  • webwiew了解?怎么实现和javascript的通信?相互双方的通信。@JavascriptInterface在?版本有bug,除了这个还有其他调用android方法的方案吗?

  • ReactiveNative了解多少

JNI和NDK熟悉么?Java和C方法之前的相互调用怎么做?

posted @ 2023-02-07 10:43  年年糕  阅读(29)  评论(0)    收藏  举报