Android 面试基础篇 |
您所在的位置:网站首页 › android基础面试题 › Android 面试基础篇 |
本文是Android面试题整理中的一篇,结合右下角目录食用更佳,包括: 架构 Activity Service BroadCast ContentProvider Fragment 架构 Android的大体架构图分为四个层次:linux内核;libraies和Android runntime;framework;Application ![]() ![]() 对Activity配置了android:configChanges="xxx"属性之后,Activity就不会在对应变化发生时重新创建,而是调用Activity的onConfigurationChanged方法。常用的有local:设备的本地位置发生了变化,一般指切换了系统语言;keyboardHidden:键盘的可访问性发生了变化,比如用户调出了键盘;orientation:屏幕方向发生了变化,比如旋转了手机屏幕。 A activity启动B activity和B activity返回A activity的生命周期执行过程 A启动B:A.onPause()→B.onCreate()→B.onStart()→B.onResume()→A.onStop B返回A:B.onPause()→A.onRestart()/A.onCreate()→A.onStart()→A.onResume()→B.onStop() Activity执行finish后的生命周期 在onCreate中执行:onCreate -> onDestroy 在onStart中执行:onCreate -> onStart -> onStop -> onDestroy 在onResume中执行:onCreate -> onStart -> onResume -> onpause -> onStop -> onDestroy 如果用了一些解耦的策略,怎么管理生命周期的? 可以用Google的LifeCycle框架 0. 引入LifeCycle框架 将控件实现LifecycleObserver接口 在Activity中中注册控件:getLifeCycle().addObderver(View); 在控件中使用: @OnLifecycleEvent(Lifecycle.Event.ON_START) Activity的启动流程![]() 设置了singleTask启动模式的Activity,它在启动的时会先在系统中查看属性值affinity等于它的属性值taskAffinity ( taskAffinity默认为包名 ) 的任务栈是否存在。如果存在这样的任务栈,它就会在这个任务栈中启动,否则就会在新任务栈中启动。 当Intent对象包含FLAG_ACTIVITY_NEW_TASK标记时,系统在查找时仍然按Activity的taskAffinity属性进行匹配,如果找到一个任务栈的taskAffinity与之相同,就将目标Activity压入此任务栈中,如果找不到则创建一个新的任务栈。 设置了singleTask启动模式的Activity在已有的任务栈中已经存在相应的Activity实例,再启动它时会把这个Activity实例上面的Activity全部结束掉。也就是说singleTask自带clear top的效果。 IntentFilter的匹配规则IntentFilter中的过滤信息有action、category、data,为了匹配过滤列表,需要同时匹配过滤列表中的action、category、data信息,否则匹配失败。 验证是否有当前Activity PackageManager的resolveActivity方法或者Intent的resolveActivity方法:如果找不到就会返回null PackageManager的queryIntentActivities方法:它返回所有成功匹配的Activity信息 如何获取当前屏幕Activity的对象?通过在Application中注册Activity生命周期的监听函数Application.registerActivityLifecycleCallbacks() onNewIntent调用时机一个Activity已经启动,当再次启动它时,如果他的启动模式(如SingleTask,SingleTop)标明不需要重新启动,会调用onNewIntent 除了用Intent 去启动一个Activity,还有其他方法吗使用adb shell am 命令 :如adb shell am start com.example.fuchenxuan/.MainActivity 或者 adb shell am broadcast -a magcomm.action.TOUCH_LETTER Android中子线程更新UI的方式 activity.runOnUiThread(runnable) 通过主线程中的Handler进行更新 通过View的post()或者postDelayed方法进行更新 Activity之间的通信方式 Intent BroadCast或者LocalBroadCast 数据存储的方式 静态变量 Service Service的启动方式 start bind Service生命周期![]() 这是因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。 IntentService IntentService 是继承自 Service,内部通过HandlerThread启动一个新线程处理耗时操作么,可以看做是Service和HandlerThread的结合体,在完成了使命之后会自动停止,适合需要在工作线程处理UI无关任务的场景 如果启动 IntentService 多次,那么每一个耗时操作会以工作队列的方式在 IntentService 的 onHandleIntent 回调方法中执行,依次去执行,使用串行的方式,执行完自动结束。 IntentService生命周期是怎样的 在所有任务执行完毕后,自动结束生命 BroadCast BroadCast的注册方式与区别 在manifest中静态注册:广播是常驻的,App关闭后仍能接收广播,唤醒App 动态的注册和注销:动态注册的广播生命周期和他的宿主相同,或者调用注销方法注销广播 Android中发送BroadCast的方式 无序广播:通过mContext.sendBroadcast(Intent)或mContext.sendBroadcast(Intent, String)发送的是无序广播(后者加了权限); 通过mContext.sendOrderedBroadcast(Intent, String, BroadCastReceiver, Handler, int, String, Bundle)发送的是有序广播(不再推荐使用)。 在无序广播中,所有的Receiver会接收到相同广播;而在有序广播中,我们可以为Receiver设置优先级,优先级高的先接收广播,并有权对广播进行处理和决定要不要继续向下传送 BroadCastReceiver处理耗时操作 BroadcastReceiver的生命周期只有一个回调方法onReceive(Context context, Intent intent);无法进行耗时操作,即使启动线程处理,也是出于非活动状态,有可能被系统杀掉。 如果需要进行耗时操作,可以启动一个service处理。 广播发送和接收的原理了解吗 继承BroadcastReceiver,重写onReceive()方法。 通过Binder机制向ActivityManagerService注册广播。 通过Binder机制向ActivityMangerService发送广播。 ActivityManagerService查找符合相应条件的广播(IntentFilter/Permission)的BroadcastReceiver,将广播发送到BroadcastReceiver所在的消息队列中。 BroadcastReceiver所在消息队列拿到此广播后,回调它的onReceive()方法。 广播传输的数据是否有限制,是多少,为什么要限制? 广播是通过Intent携带需要传递的数据的 Intent是通过Binder机制实现的 Binder对数据大小有限制,不同room不一样,一般为1M Localbroadcast本地广播,只有本进程中的receivers能接收到此广播 实现原理(监听者模式): LocalBroadcastManager是一个单例 在LocalBroadcastManager实例中维护一个Action和ReceiverRecord的Map.(ReceiverRecord是reveiver和intentfilter的组合) 当调用LocalBroadcastManager的sendBroadcast方法时,会从2中的map找到合适的receiver,让后加到待执行的队列mPendingBroadcasts,并通过Handler发送一个空消息(此Handler运行在主线程中,是创建manager时创建的) handler 的handle方法收到消息,从mPendingBroadcasts取出receiver并调用onreceive方法 其他:删除方法是通过一个辅助的hashmap实现的,hashmap存储了receiver和receiverRecord ContentProvider 请介绍下ContentProvider是如何实现数据共享的 准确的说,ContentProvider是一个APP间共享数据的接口。一个程序可以通过实现一个Content provider的抽象接口将自己的数据完全暴露出去,数据可以是SqLite中的,也可以是文件或者其他类型。 使用方式: 在A APP中实现建ContentProvider,并在Manifest中生命它的Uri和权限 在B APP中注册权限,并通过ContentResolver和Uri进行增删改查 扩展:ContentProvider底层是通过Binder机制来实现跨进程间通信,通过匿名共享内存方式进行数据的传输 一个应用进程有16个Binder线程去和远程服务进行交互,而每个线程可占用的缓存空间是128KB,超过会报异常。 每个ContentProvider的操作是在哪个线程中运行的呢(其实我们关心的是UI线程和工作线程)?比如我们在UI线程调用getContentResolver().query查询数据,而当数据量很大时(或者需要进行较长时间的计算)会不会阻塞UI线程呢? ContentProvider和调用者在同一个进程,ContentProvider的方法(query/insert/update/delete等)和调用者在同一线程中 ContentProvider和调用者在不同的进程,ContentProvider的方法会运行在它自身所在进程的一个Binder线程中 ContentProvider、ContentResolver与ContentObserver之间的关系是什么? ContentProvider:管理数据,提供数据的增删改查操作,数据源可以是数据库、文件、XML、网络等,ContentProvider为这些数据的访问提供了统一的接口,可以用来做进程间数据共享。 ContentResolver:ContentResolver可以不同URI操作不同的ContentProvider中的数据,外部进程可以通过ContentResolver与ContentProvider进行交互。 ContentObserver:观察ContentProvider中的数据变化,并将变化通知给外界。 Fragment Fragment生命周期onAttach -> onCreate -> onCreateView -> onActivityCreate -> onStart -> onResume -> onPause -> onStop -> onDestoryView -> onDestory -> onDetach ![]() 举例:getActivity()空指针:这种情况一般发生在在异步任务里调用getActivity(),而Fragment已经onDetach()。 Fragment 有什么优点, Fragment和View可以相互替换嘛 Fragment为了解决Andriod碎片化而产生的 Fragment和View都有助于界面复用 Fragment的复用粒度更大,包含生命周期和业务逻辑,通常包含好几个View View通常更关注视图的实现 Fragment add replace 区别 replace 先删除容器中的内容,再添加 add直接添加,可以配合hide适用 参考资料LearningNotes 40 个 Android 面试题 https://www.nowcoder.com/discuss/3043 http://weixin.niurenqushi.com/article/2017-03-17/4790406.html https://blog.csdn.net/vfush/article/details/51481127 https://blog.csdn.net/vfush/article/details/51790079 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |