android总结

作者: MrWang915 | 来源:发表于2017-05-10 22:40 被阅读187次

    线程和进程的区别是啥

    详见 http://www.jianshu.com/p/04c3706521b5


    线程切换如何做,有啥性能影响

    handler runOnThread asyncTask  


    线程之间如何进行同步

    synchronized volatile ReentrantLock


    死锁如何造成的,如何避免

    死锁是指多个进程因竞争资源而造成的一种僵局(互相等待)

    进程在运行过程中,请求和释放资源的顺序不当,会导致死锁。

    1 互斥

    只有互斥才可以产生死锁,两个进程共同操作一个资源,那么,同一时间只能一个进程来操作,那么另一个进程必须等待,此进程不释放,另一个永远等待。产生死锁

    2 不可以强占

    两个进程,一个进程占有某一个资源,另一个不可以强行占有我的资源,如果可以占有,那么两个进程都可以操作资源,那么就不会产生死锁。

    3请求保持

    我请求某一个资源的同时,保持对另一个资源的占有。那么我不释放,那么另一个进程才可能等待;如果释放,那么共同操作同一个资源,不会等待,也就不会死锁。

    4 循环等待

    a等待b的释放资源,b等待c释放资源,c却等待a释放资源。都在循环等待。

    避免: 

    加锁顺序(线程按照一定的顺序加锁)

    加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)

    死锁检测


    进程间通信方式,尤其是Android中的进程间通信方式

    messager (串行处理)

    AIDL (可并发处理)

    TCP/UDP的区别

    1.基于连接与无连接;

    2.对系统资源的要求(TCP较多,UDP少);

    3.UDP程序结构较简单;

    4.流模式与数据报模式 ;

    5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。

    参考 http://zhangjiangxing-gmail-com.iteye.com/blog/646880

    TCP三次握手和四次挥手流程,为什么要进行第三次握手,为什么是四次挥手而不是三次挥手就完了

    同步连接双方的序列号和确认号并交换 TCP窗口大小信息。

    1 为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误

    2 解决“网络中存在延迟的重复分组”的问题

    3 保证连接是双工的,可靠更多的是通过重传机制来保证的。

    4为了保证服务端能收接受到客户端的信息并能做出正确的应答而进行前两次握手,为了保证客户端能够接收到服务端的信息并能做出正确的应答而进行后两次握手。 

    http://www.jianshu.com/p/c1d6a294d3c0

    http://blog.163.com/wangzhenbo85@126/blog/static/1013632822013423502833/?suggestedreading&wumii

    http://www.cr173.com/exam/Cisco_17954_1.html

    为啥挥手需要四次:

    这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。


    TCP的状态 (SYN, FIN, ACK, PSH, RST, URG)

    SYN表示建立连接,

    FIN表示关闭连接,

    ACK表示响应,

    PSH表示有 DATA数据传输,

    RST表示连接重置。

    http://www.cnblogs.com/azraelly/archive/2012/12/25/2832393.html


    即时通讯中为什么大多使用UDP

    TCP做心跳检测网络情况

    HTTP的几种请求方式以及适用情况

    HTTPS建立连接的流程,证书有什么用,怎么解决中间人劫持攻击

    HTTP 加密

    MD5对称加密s'd'd'd'd'd'd'd'd'd'd'd'd'd'd'd'd'd'd

    HTTP是怎么做的断点重传,记得当时并不知道,就按照自己的理解回答了应用层断点续传的方案,然后HTTP估计也是差不多的思路,后来查了一下,还确实差不多。



    观察者模式,这在Android中比较常用

    迭代器模式


    Activity的四种启动方式,


    Android的消息机制,理清Handler、Looper、Message和MessageQueue之间的关系即可

    http://www.jianshu.com/p/ac50ba6ba3a2


    Service和IntentService的区别

    自定义View的几种方式

    继承view ,viewGroup 

    Android动画的几种方式

    进程间通信方式

    序列化相关知识,怎么序列化,为啥要序列化

    1 分别是实现Serializable接口和Parcelable接口

    永久性保存对象,保存对象的字节序列到本地文件中

    对象在网络中传递

    对象在IPC间传递


    触摸事件传递流程

    如何设计缓存模块

    三级缓存  

    内存 (LruCache)--》硬盘(DiskLruCache) --》网络(Volley……第三方框架)


    如何做持久化

    1 SharedPreferences  2 内部存储(存储到手机内部存储空间) 3 外部卡存储sdcard

    http://blog.csdn.net/chaoyong918/article/details/42440221


    解决bitmap 之OOM

    加载合理尺寸的Bitmap

    避免反复解码、重复加载Bitmap

    控制Bitmap的生命周期,合理回收

    引入lrucache dislrucache


    死锁是如何造成的

    多线程以及多进程改善了系统资源的利用率并提高了系统 的处理能力。然而,并发执行也带来了新的问题——死锁。所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。

    http://blog.csdn.net/ls5718/article/details/51896159


    线程间  进程间通信

    1 全局变量 2消息传递(handler) 3 参数传递(初始化函数,如asyncTask) 4 线程同步() 5 runOnThread(Runnable)

    2 message aidl

    主线程给子线程传递消息 

    1 可在子线程声明loope    

    2 构造函数传递 

    3 共享变量


    map list


    性能优化经验工具

    traceview    ddms


    横竖屏切换 经过的生命周期

    onCreate-->

    onStart-->

    onResume-->

    3、按crtl+f12切换成横屏时

    onSaveInstanceState-->

    onPause-->

    onStop-->

    onDestroy-->

    onCreate-->

    onStart-->

    onRestoreInstanceState-->

    onResume-->

    设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

    补充一点,当前Activity产生事件弹出Toast和AlertDialog的时候Activity的生命周期不会有改变

    Activity运行时按下HOME键(跟被完全覆盖是一样的):onSaveInstanceState --> onPause --> onStop       onRestart -->onStart--->onResume

    Activity未被完全覆盖只是失去焦点:onPause--->onResume

    http://www.cnblogs.com/wjhblogs/p/4688918.html


    内存优化

    设计模式

    源码观看(handler volley imageload )

    项目上的提问

    asyncTask

    Android部分(给出重点部分):

    1. Activity 系列问题

    1.1 绘制Activity生命周期流程图

    1.2 介绍下不同场景下Activity生命周期的变化过程

    启动Activity: onCreate()--->onStart()--->onResume(),Activity进入运行状态。

    Activity退居后台: 当前Activity转到新的Activity界面或按Home键回到主屏: onPause()--->onStop(),进入停滞状态。

    Activity返回前台: onRestart()--->onStart()--->onResume(),再次回到运行状态。

    Activity退居后台,且系统内存不足, 系统会杀死这个后台状态的Activity,若再次回到这个Activity,则会走onCreate()-->onStart()--->onResume()

    锁定屏与解锁屏幕只会调用onPause(),而不会调用onStop方法,开屏后则调用onResume()

    1.3 内存不足时系统会杀掉后台的Activity,若需要进行一些临时状态的保存,在哪个方法进行?

    Activity的 onSaveInstanceState() 和

    onRestoreInstanceState()并不是生命周期方法,它们不同于

    onCreate()、onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。除非该activity是被用户主动销毁的,通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。

    1.4 onSaveInstanceState()被执行的场景有哪些:

    系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,因此系统都会调用onSaveInstanceState(),让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则

    当用户按下HOME键时

    长按HOME键,选择运行其他的程序时

    锁屏时

    从activity A中启动一个新的activity时

    屏幕方向切换时

    1.5 介绍Activity的几中启动模式,并简单说说自己的理解或者使用场景

    2. Service系列问题

    2.1 注册Service需要注意什么

    Service还是运行在主线程当中的,所以如果需要执行一些复杂的逻辑操作,最好在服务的内部手动创建子线程进行处理,否则会出现UI线程被阻塞的问题

    2.2 Service与Activity怎么实现通信

    方法一:

    添加一个继承Binder的内部类,并添加相应的逻辑方法

    重写Service的onBind方法,返回我们刚刚定义的那个内部类实例

    Activity中创建一个ServiceConnection的匿名内部类,并且重写里面的onServiceConnected方法和onServiceDisconnected方法,这两个方法分别会在活动与服务成功绑定以及解除绑定的时候调用,在onServiceConnected方法中,我们可以得到一个刚才那个service的binder对象,通过对这个binder对象进行向下转型,得到我们那个自定义的Binder实例,有了这个实例,做可以调用这个实例里面的具体方法进行需要的操作了

    方法二 通过BroadCast(广播)的形式    当我们的进度发生变化的时候我们发送一条广播,然后在Activity的注册广播接收器,接收到广播之后更新视图

    2.3 介绍源码中binder机制

    2.4 IntentService与Service的区别

    IntentService是Service的子类,是一个异步的,会自动停止的服务,很好解决了传统的Service中处理完耗时操作忘记停止并销毁Service的问题

    会创建独立的worker线程来处理所有的Intent请求;

    会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;

    所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service;

    为Service的onBind()提供默认实现,返回null;

    为Service的onStartCommand提供默认实现,将请求Intent添加到队列中;

    IntentService不会阻塞UI线程,而普通Serveice会导致ANR异常

    Intentservice若未执行完成上一次的任务,将不会新开一个线程,是等待之前的任务完成后,再执行新的任务,等任务完成后再次调用stopSelf()

    3. Handle系列问题

    3.1 介绍Handle的机制

    Handler通过调用sendmessage方法把消息放在消息队列MessageQueue中,Looper负责把消息从消息队列中取出来,重新再交给Handler进行处理,三者形成一个循环

    通过构建一个消息队列,把所有的Message进行统一的管理,当Message不用了,并不作为垃圾回收,而是放入消息队列中,供下次handler创建消息时候使用,提高了消息对象的复用,减少系统垃圾回收的次数

    每一个线程,都会单独对应的一个looper,这个looper通过ThreadLocal来创建,保证每个线程只创建一个looper,looper初始化后就会调用looper.loop创建一个MessageQueue,这个方法在UI线程初始化的时候就会完成,我们不需要手动创建

    3.2 谈谈对HandlerThread的理解

    4. ListView系列问题

    4.1 ListView卡顿的原因与性能优化,越多越好

    重用converView: 通过复用converview来减少不必要的view的创建,另外Infalte操作会把xml文件实例化成相应的View实例,属于IO操作,是耗时操作。

    减少findViewById()操作: 将xml文件中的元素封装成viewholder静态类,通过converview的setTag和getTag方法将view与相应的holder对象绑定在一起,避免不必要的findviewbyid操作

    避免在 getView 方法中做耗时的操作: 例如加载本地 Image 需要载入内存以及解析      Bitmap        ,都是比较耗时的操作,如果用户快速滑动listview,会因为getview逻辑过于复杂耗时而造成滑动卡顿现象。用户滑动时候不要加载图片,待滑动完成再加载,可以使用这个第三方库glide

    Item的布局层次结构尽量简单,避免布局太深或者不必要的重绘

    尽量能保证 Adapter 的 hasStableIds() 返回 true这样在      notifyDataSetChanged() 的时候,如果item内容并没有变化,ListView 将不会重新绘制这个 View,达到优化的目的

    在一些场景中,ScollView内会包含多个ListView,可以把listview的高度写死固定下来。由于ScollView在快速滑动过程中需要大量计算每一个listview的高度,阻塞了UI线程导致卡顿现象出现,如果我们每一个item的高度都是均匀的,可以通过计算把listview的高度确定下来,避免卡顿现象出现

    使用 RecycleView 代替listview: 每个item内容的变动,listview都需要去调用notifyDataSetChanged来更新全部的item,太浪费性能了。RecycleView可以实现当个item的局部刷新,并且引入了增加和删除的动态效果,在性能上和定制上都有很大的改善

    ListView 中元素避免半透明:      半透明绘制需要大量乘法计算,在滑动时不停重绘会造成大量的计算,在比较差的机子上会比较卡。 在设计上能不半透明就不不半透明。实在要弄就把在滑动的时候把半透明设置成不透明,滑动完再重新设置成半透明。

    尽量开启硬件加速:      硬件加速提升巨大,避免使用一些不支持的函数导致含泪关闭某个地方的硬件加速。当然这一条不只是对 ListView。

    4.2 怎么实现一个部分更新的 ListView?

    4.3 怎么实现ListView多种布局?

    4.4 ListView与数据库绑定的实现

    5. JNI系列问题

    5.1 如何使用JNI

    JAVA中声明native 方法如private native String printJNI(String inputStr);

    使用javah工具生成.h头文件这时候头文件中就会自动生成对应的函数JNIEXPORT jstring JNICALL

    Java_com_wenming_HelloWorld_printJNI

    实现JNI原生函数源文件,新建HelloWorld.c文件,对刚才自动生成的函数进行具体的逻辑书写,例如返回一个java叫做HelloWorld的字符串等

    编译生成动态链接so文件**

    Java中调用Sysytem.load方法把刚才的so库加载进来,就可以调用native方法了

    5.2 如何通过JNI传递String对象

    Java的String和C++的string是不能对等起来的,所以当我们拿到.h文件下面的jstring对象,会做一次转换我们把jstring转换为C下面的char*类型, 获取值

    constchar* str;

    str = env->GetStringUTFChars(prompt,false);

    赋予值

    char* tmpstr ="return string succeeded";

    jstring rtstr = env->NewStringUTF(tmpstr);

    6. OOM系列问题

    6.1 什么OOM?

    OOM全称是Out Of Merrory,Android系统的每一个应用程序都设置一个硬性的Dalvik Heap Size最大限制阈值,如果申请的内存资源超过这个限制,系统就会抛出OOM错误

    6.2 内存泄漏有哪些场景以及解决方法

    类的静态变量持有大数据对象静态变量长期维持到大数据对象的引用,阻止垃圾回收。

    非静态内部类存在静态实例非静态内部类会维持一个到外部类实例的引用,如果非静态内部类的实例是静态的,就会间接长期维持着外部类的引用,阻止被回收掉。

    资源对象未关闭资源性对象比如(Cursor,File文件等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,      以便它们的缓冲及时回收内存。它们的缓冲不仅存在于java虚拟机内,还存在于java虚拟机外。      如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄露。解决办法:      比如SQLiteCursor(在析构函数finalize(),如果我们没有关闭它,它自己会调close()关闭),      如果我们没有关闭它,系统在回收它时也会关闭它,但是这样的效率太低了。      因此对于资源性对象在不使用的时候,应该调用它的close()函数,将其关闭掉,然后才置为null.      在我们的程序退出时一定要确保我们的资源性对象已经关闭。      程序中经常会进行查询数据库的操作,但是经常会有使用完毕Cursor后没有关闭的情况。如果我们的查询结果集比较小,      对内存的消耗不容易被发现,只有在常时间大量操作的情况下才会复现内存问题,这样就会给以后的测试和问题排查带来困难和风险,记得try catch后,在finally方法中关闭连接

    Handler内存泄漏Handler作为内部类存在于Activity中,但是Handler生命周期与Activity生命周期往往并不是相同的,比如当Handler对象有Message在排队,则无法释放,进而导致本该释放的Acitivity也没有办法进行回收。解决办法

    声明handler为static类,这样内部类就不再持有外部类的引用了,就不会阻塞Activity的释放

    如果内部类实在需要用到外部类的对象,可在其内部声明一个弱引用引用外部类。

    public class MainActivity extends Activity {

    private CustomHandler mHandler;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    mHandler = new CustomHandler(this);

    }

    static class CustomHandlerextends Handler {

    // 内部声明一个弱引用,引用外部类

    private WeakReference activityWeakReference;

    public MyHandler(MyActivity activity) {

    activityWeakReference= new WeakReference(activity);

    }

    // ... ...

    }

    }

    在Activity onStop或者onDestroy的时候,取消掉该Handler对象的Message和Runnable

    Override

    public void onDestroy() {

    //  If null, all callbacks and messages will be removed.

    mHandler.removeCallbacksAndMessages(null);

    }

    一些不良代码习惯有些代码并不造成内存泄露,但是他们的资源没有得到重用,频繁的申请内存和销毁内存,消耗CPU资源的同时,也引起内存抖动解决方案如果需要频繁的申请内存对象和和释放对象,可以考虑使用对象池来增加对象的复用。 例如ListView便是采用这种思想,通过复用converview来避免频繁的GC

    6.2 如何避免 OOM 问题的出现

    1. 使用更加轻量的数据结构例如,我们可以考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构。通常的HashMap的实现方式更加消耗内存,因为它需要一个额外的实例对象来记录Mapping操作。另外,SparseArray更加高效,在于他们避免了对key与value的自动装箱(autoboxing),并且避免了装箱后的解箱。

    2. 避免在Android里面使用EnumAndroid官方培训课程提到过“Enums often  require more than twice as much memory as static constants. You should  strictly avoid using enums on Android.”,具体原理请参考《Android性能优化典范(三)》,所以请避免在Android里面使用到枚举。

    3. 减小Bitmap对象的内存占用Bitmap是一个极容易消耗内存的大胖子,减小创建出来的Bitmap的内存占用可谓是重中之重,,通常来说有以下2个措施:inSampleSize:缩放比例,在把图片载入内存之前,我们需要先计算出一个合适的缩放比例,避免不必要的大图载入。decode format:解码格式,选择ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差异

    4.Bitmap对象的复用缩小Bitmap的同时,也需要提高BitMap对象的复用率,避免频繁创建BitMap对象,复用的方法有以下2个措施LRUCache:  “最近最少使用算法”在Android中有极其普遍的应用。ListView与GridView等显示大量图片的控件里,就是使用LRU的机制来缓存处理好的Bitmap,把近期最少使用的数据从缓存中移除,保留使用最频繁的数据,inBitMap高级特性:利用inBitmap的高级特性提高Android系统在Bitmap分配与释放执行效率。使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的Bitmap会尝试去使用之前那张Bitmap在Heap中所占据的pixel data内存区域,而不是去问内存重新申请一块区域来存放Bitmap。利用这种特性,即使是上千张的图片,也只会仅仅只需要占用屏幕所能够显示的图片数量的内存大小

    4. 使用更小的图片在涉及给到资源图片时,我们需要特别留意这张图片是否存在可以压缩的空间,是否可以使用更小的图片。尽量使用更小的图片不仅可以减少内存的使用,还能避免出现大量的InflationException。假设有一张很大的图片被XML文件直接引用,很有可能在初始化视图时会因为内存不足而发生InflationException,这个问题的根本原因其实是发生了OOM。

    5.StringBuilder在有些时候,代码中会需要使用到大量的字符串拼接的操作,这种时候有必要考虑使用StringBuilder来替代频繁的“+”。

    4.避免在onDraw方法里面执行对象的创建类似onDraw等频繁调用的方法,一定需要注意避免在这里做创建对象的操作,因为他会迅速增加内存的使用,而且很容易引起频繁的gc,甚至是内存抖动。

    5. 避免对象的内存泄露android中内存泄漏的场景以及解决办法,参考上一问

    7.  ANR 系列问题

    7.1 什么ANR

    ANR全称Application Not Responding,意思就是程序未响应。如果一个应用无法响应用户的输入,系统就会弹出一个ANR对话框,用户可以自行选择继续等待亦或者是停止当前程序。一旦出现下面两种情况,则弹出ANR对话框

    应用在5秒内未响应用户的输入事件(如按键或者触摸)

    BroadcastReceiver未在10秒内完成相关的处理

    7.2 ANR是怎么引起的?

    主线程中存在耗时的计算-

    主线程被IO操作(从4.0之后网络IO不允许在主线程中)阻塞。-

    主线程中错误的操作,比如Thread.wait或者Thread.sleep等

    7.3 如何避免ANR问题的出现

    基本思路就是把一些耗时操作放到子线程中处理

    使用AsyncTask处理耗时IO操作。

    降低子线程优先级使用Thread或者HandlerThread时,调用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)设置优先级,否则仍然会降低程序响应,因为默认Thread的优先级和主线程相同。

    使用Handler处理子线程结果,而不是使用Thread.wait()或者Thread.sleep()来阻塞主线程。

    Activity的onCreate和onResume回调中尽量避免耗时的代码

    BroadcastReceiver中onReceive代码也要尽量减少耗时操作建议使用IntentService处理。IntentService是一个异步的,会自动停止的服务,很好解决了传统的Service中处理完耗时操作忘记停止并销毁Service的问题

    8. Asynctask问题

    8.1 AsynTask为什么要设计为只能够一次任务?

    最核心的还是线程安全问题,多个子线程同时运行,会产生状态不一致的问题。所以要务必保证只能够执行一次

    8.2 AsynTask造成的内存泄露的 问题怎么解决,》比如非静态内部类AsynTask会隐式地持有外部类的引用,如果其生命周期大于外部activity的生命周期,就会出现内存泄漏

    注意要复写AsynTask的onCancel方法,把里面的socket,file等,该关掉的要及时关掉

    在 Activity 的onDestory()方法中调用Asyntask.cancal方法

    Asyntask内部使用弱引用的方式来持有Activity

    8.3 若Activity已经销毁,此时AsynTask执行完并且返回结果,会报异常吗?

    当一个App旋转时,整个Activity会被销毁和重建。当Activity重启时,AsyncTask中对该Activity的引用是无效的,因此onPostExecute()就不会起作用,若AsynTask正在执行,折会报

    view not attached to window manager 异常

    同样也是生命周期的问题,在 Activity 的onDestory()方法中调用Asyntask.cancal方法,让二者的生命周期同步

    8.4 Activity销毁但Task如果没有销毁掉,当Activity重启时这个AsyncTask该如何解决?

    还是屏幕旋转这个例子,在重建Activity的时候,会回掉Activity.onRetainNonConfigurationInstance()重新传递一个新的对象给AsyncTask,完成引用的更新

    9. Android触摸分发机制

    9.1 介绍触摸事件的分发机制

    (1) 事件从Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的View(ViewGroup)开始一直往下(子View)传递。子View可以通过onTouchEvent()对事件进行处理。

    (2) 事件由父View(ViewGroup)传递给子View,ViewGroup可以通过onInterceptTouchEvent()对事件做拦截,停止其往下传递。

    (3) 如果事件从上往下传递过程中一直没有被停止,且最底层子View没有消费事件,事件会反向往上传递,这时父View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到Activity的onTouchEvent()函数。

    (4) 如果View没有对ACTION_DOWN进行消费,之后的其他事件不会传递过来。

    (5) OnTouchListener优先于onTouchEvent()对事件进行消费。

    上面的消费即表示相应函数返回值为true。

    9.2

    View中 setOnTouchListener的onTouch,onTouchEvent,onClick的执行顺序

    追溯到View的dispatchTouchEvent源码查看,有这么一段代码

    public boolean dispatchTouchEvent(MotionEvent event) {

    if (!onFilterTouchEventForSecurity(event)) {

    return false;

    }

    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&

    mOnTouchListener.onTouch(this, event)) {

    return true;

    }

    return onTouchEvent(event);

    }

    当以下三个条件任意一个不成立时,

    mOnTouchListener不为null

    view是enable的状态

    mOnTouchListener.onTouch(this, event)返回true,

    函数会执行到onTouchEvent。在这里我们可以看到,首先执行的是mOnTouchListener.onTouch的方法,然后是onTouchEvent方法

    继续追溯源码,到onTouchEvent()观察,发现在处理ACTION_UP事件里有这么一段代码

    if (!post(mPerformClick)) {

    performClick();

    }

    此时可知,onClick方法也在最后得到了执行

    所以三者的顺序是:

    setOnTouchListener() 的onTouch

    onTouchEvent()

    onClick()

    10. Dalvik虚拟机系列问题

    10.1 什么是Dalvik虚拟机?

    Dalvik虚拟机是Android平台的核心。它可以支持.dex格式的程序的运行,.dex格式是专为Dalvik设计的一种压缩格式,可以减少整体文件尺寸,提高I/O操作的速度,适合内存和处理器速度有限的系统。

    10.2 Dalvik虚拟机的作用是什么?

    Dalvik虚拟机主要是完成对象生命周期管理,内存回收,堆栈管理,线程管理,安全和异常管理等等重要功能。

    10.3 Dalvik虚拟机与JVM有什么区别

    Dalvik 基于寄存器,而 JVM 基于栈。基于寄存器的虚拟机对于更大的程序来说,在它们编译的时候,花费的时间更短。

    Dalvik执行.dex格式的字节码,而JVM执行.class格式的字节码。

    10.4 每个应用程序对应多少个Dalvik虚拟机

    每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行 ,而所有的Android应用的线程都对应一个Linux线程

    11. 注册广播接收器有哪几种方式,有什么区别

    静态注册:在AndroidManifest.xml文件中进行注册,当App退出后,Receiver仍然可以接收到广播并且进行相应的处理

    动态注册:在代码中动态注册,当App退出后,也就没办法再接受广播了

    12. 显示Intent与隐式Intent的区别

    对明确指出了目标组件名称的Intent,我们称之为“显式Intent”。 对于没有明确指出目标组件名称的Intent,则称之为“隐式 Intent”。

    对于隐式意图,在定义Activity时,指定一个intent-filter,当一个隐式意图对象被一个意图过滤器进行匹配时,将有三个方面会被参考到:

    动作(Action)

    类别(Category ['kætɪg(ə)rɪ] )

    数据(Data )

    13. Android中的动画有哪些,区别是什么

    逐帧动画(Drawable Animation): 加载一系列Drawable资源来创建动画,简单来说就是播放一系列的图片来实现动画效果,可以自定义每张图片的持续时间

    补间动画(Tween Animation): Tween可以对View对象实现一系列简单的动画效果,比如位移,缩放,旋转,透明度等等。但是它并不会改变View属性的值,只是改变了View的绘制的位置,比如,一个按钮在动画过后,不在原来的位置,但是触发点击事件的仍然是原来的坐标。

    属性动画(Property Animation): 动画的对象除了传统的View对象,还可以是Object对象,动画结束后,Object对象的属性值被实实在在的改变了

    14. 不使用动画,怎么实现一个动态的 View?

    15. Postvalidata与Validata有什么区别?

    16. 如何自定义ViewGroup?

    17. View的绘制流程

    measure()方法,layout(),draw()三个方法主要存放了一些标识符,来判断每个View是否需要再重新测量,布局或者绘制,主要的绘制过程还是在onMeasure,onLayout,onDraw这个三个方法中

    1.onMesarue()为整个View树计算实际的大小,即设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性:  mMeasureWidth),每个View的控件的实际宽高都是由父视图和本身视图决定的。

    2.onLayout()为将整个根据子视图的大小以及布局参数将View树放到合适的位置上。

    3. onDraw()开始绘制图像,绘制的流程如下

    首先绘制该View的背景

    调用onDraw()方法绘制视图本身  (每个View都需要重载该方法,ViewGroup不需要实现该方法)

    如果该View是ViewGroup,调用dispatchDraw ()方法绘制子视图

    绘制滚动条

    18. 数据持久化的四种方式有哪些?

    文件存储: 通过java.io.FileInputStream和java.io.FileOutputStream这两个类来实现对文件的读写,java.io.File类则用来构造一个具体指向某个文件或者文件夹的对象。

    SharedPreferences: SharedPreferences是一种轻量级的数据存储机制,他将一些简单的数据类型的数据,包括boolean类型,int类型,float类型,long类型以及String类型的数据,以键值对的形式存储在应用程序的私有Preferences目录(/data/data/<包名>/shared_prefs/)中,这种Preferences机制广泛应用于存储应用程序中的配置信息。

    SQLite数据库: 当应用程序需要处理的数据量比较大时,为了更加合理地存储、管理、查询数据,我们往往使用关系数据库来存储数据。Android系统的很多用户数据,如联系人信息,通话记录,短信息等,都是存储在SQLite数据库当中的,所以利用操作SQLite数据库的API可以同样方便的访问和修改这些数据。

    ContentProvider: 主要用于在不同的应用程序之间实现数据共享的功能,不同于sharepreference和文件存储中的两种全局可读写操作模式,内容提供其可以选择只对哪一部分数据进行共享,从而保证我们程序中的隐私数据不会有泄漏的风险

    19. fragement里面可以再嵌套fragment?

    20. Socker编程的步骤

    21. Activity中如何动态的添加Fragment

    22. Scrollview怎么判断是否滑倒底部

    23. 什么是 MVC 模式?MVC 模式的好处是什么?

    24. 应用常驻后台,避免被第三方杀掉的方法,讲讲你用过的奇淫巧技?

    Service设置成START_STICKYkill 后会被重启(等待5秒左右),重传Intent,保持与重启前一样

    通过 startForeground将进程设置为前台进程,      做前台服务,优先级和前台应用一个级别​,除非在系统内存非常缺,否则此进程不会被 kill

    双进程Service: 让2个进程互相保护**,其中一个Service被清理后,另外没被清理的进程可以立即重启进程

    QQ黑科技: 在应用退到后台后,另起一个只有 1 像素的页面停留在桌面上,让自己保持前台状态,保护自己不被后台清理工具杀死

    在已经root的设备下,修改相应的权限文件,将App伪装成系统级的应用Android4.0系列的一个漏洞,已经确认可行

    用C编写守护进程(即子进程):      Android系统中当前进程(Process)fork出来的子进程,被系统认为是两个不同的进程。当父进程被杀死的时候,子进程仍然可以存活,并不受影响。鉴于目前提到的在Android->- Service层做双守护都会失败,我们可以fork出c进程,多进程守护。死循环在那检查是否还存在,具体的思路如下(Android5.0以上的版本不可行)

    用C编写守护进程(即子进程),守护进程做的事情就是循环检查目标进程是否存在,不存在则启动它。

    在NDK环境中将1中编写的C代码编译打包成可执行文件(BUILD_EXECUTABLE)。主进程启动时将守护进程放入私有目录下,赋予可执行权限,启动它即可。

    联系厂商,加入白名单

    25.Context与ApplicationContext的区别,分别用在什么情况下

    Application的Context是一个全局静态变量,SDK的说明是只有当你引用这个context的生命周期超过了当前activity的生命周期,而和整个应用的生命周期挂钩时,才去使用这个application的context。

    在android中context可以作很多操作,但是最主要的功能是加载和访问资源。在android中有两种context,一种是

    application context,一种是activity context,通常我们在各种类和方法间传递的是activity context。

    26. 同一个应用程序的不同Activity可以运行在不同的进程中么?如果可以,举例说明;

    27. Java中的线程同步有哪几种方式,举例说明;

    28. dp, dip,

    dpi, px, sp是什么意思以及他们的换算公式?layout-sw400dp, layout-h400dp分别代表什么意思;

    29. 如何让两个TextView在一个RelativeLayout水平居中显示;

    30. 如何画出一个印章的图案

    31. 如何实现一个字体的描边与阴影效果

    32. 设计一个从网络请求数据,图片,并加载到列表的系统,画出客户端架构并简单的分析下;

    33.  设计一个文件的断点续传系统;

    34. 设计一个图片缓存加载机制

    数据结构与算法部分:

    给最外层的rootview,把这个根视图下的全部button背景设置成红色,手写代码,不许用递归

    给一串字符串比如abbbcccd,输出a1b3c3d1,手写代码(注意有个别字符可能会出现十次以上的情况)

    一个序列,它的形式是12349678,9是最高峰,经历了一个上升又下降的过程,找出里面的最大值的位置,要求效率尽可能高

    二叉查找树的删除操作,手写代码

    反转链表,手写代码

    二分查找,手写代码

    有海量条 url,其中不重复的有300万条,现在希望挑选出重复出现次数最高的 url,要求效率尽可能的高

    一篇英语文章,去掉字符只留下k个,如何去掉才能使这k个字符字典序最小

    弗洛伊德算法和 Dijkstra算法的区别?复杂度是多少?讲讲 Dijkstra算法的具体过程

    反转字符串,要求手写代码,优化速度、优化空间

    给出两个无向图,找出这2个无向图中相同的环路。手写代码

    单例模式,手写代码

    生产者与消费者,手写代码

    二叉树镜像,手写代码

    最长不重复子串(最长重复子串),手写代码

    操作系统部分:

    分别从操作系统的内存角度与进程线程角度解释分析堆,栈二者的区别

    什么是事务?

    OSI七层模型有哪些,各层次的作用

    TCP的三次握手过程,四次挥手过程,为什么需要三次?

    说说操作系统中进程的通信方式

    浏览器输入地址之后,之后的过程

    谈谈 HTTP 中Get 和 Post 方法的区别?

    相关文章

      网友评论

        本文标题:android总结

        本文链接:https://www.haomeiwen.com/subject/fpsmtxtx.html