Android应用层面试题

 

四大组件是什么?

Activity【活动】:用于表现功能。 Service【服务】:后台运行服务,不提供界面呈现。 BroadcastReceiver【广播接收器】:用来接收广播。 Content Provider【内容提供商】:支持在多个应用中存储和读取数据,相当于数据库。

Activity生命周期?

参看《Activity组件》

Fragment生命周期?

完整:setUserVisibleHint(false) -> onAttach -> onCreate -> setUserVisibleHint(true) -> onCreateView -> onActivityCreated -> onStart -> onResume -> onPause -> onStop -> onDestroyView -> onDestroy -> onDetach 已经在BackStack中的Fragment再出现:onCreateView > onViewCreated > onActivityCreated > onStart > onResume 有BackStack标记的Fragment被替换:onPause > onStop > onDestroyView

Service生命周期?

参看《Service组件》

Activity的四种启动模式对比?

Standard:标准的启动模式,如果需要启动一个activity就会创建该activity的实例。也是activity的默认启动模式。 SingeTop:如果启动的activity已经位于栈顶,那么就不会重新创建一个新的activity实例。而是复用位于栈顶的activity实例对象。如果不位于栈顶仍旧会重新创建activity的实例对象。应用场景:IM对话框、新闻客户端推送。 SingleTask:设置了singleTask启动模式的activity在启动时,如果位于activity栈中,就会复用该activity,这样的话,在该实例之上的所有activity都依次进行出栈操作,即执行对应的onDestroy()方法,直到当前要启动的activity位于栈顶。一般应用在网页的图集,一键退出当前的应用程序。应用场景:应用主界面。 singleInstance:如果使用singleInstance启动模式的activity在启动的时候会复用已经存在的activity实例。不管这个activity的实例是位于哪一个应用当中,都会共享已经启动的activity的实例对象。使用了singlestance的启动模式的activity会单独的开启一个共享栈,这个栈中只存在当前的activity实例对象。应用场景:呼叫来电。 从所属task、是否允许多个实例、是否生成新实例、是否独占task四方面对比。

如何实现无限循环的Banner控件?

1.ViewPager + View 在首项前添加一个末项,在末项后添加一个首项; 重写onPageScrollStateChanged(),当切换到假首项时,无动画跳转到真首项;当切换到假末项时,无动画跳转到真末项; 重写onPageScrolled(),需要把position修改为真position; 2.RecycleView

如何在fragment之间传递数据?

属于同一Activity的,通过在Activity中添加public方法实现;不属于同一Activity的,通过广播实现。

什么时候用startService,什么时候用bindService?

如何绑定Service?

1、创建service类和activity类; 2、在service类中定义一个内部类继承自Binde类,实现getService方法,返回Service实例;在Service的onBind方法中返回这个Binder子类的实例; 3、在activity中调用bindService方法完成绑定;第一个参数是Intent实例;第二个参数是ServiceConnection实例;第三个参数是一个flag。 BIND_AUTO_CREATE:绑定完成后就启动目标service。 BIND_NOT_FOREGROUND:确保被绑定的service永远不会有运行于前台的优先级,因为默认情况下,绑定一个service会提高它的优先级。 BIND_ABOVE_CLIENT:确保客户端处于前台时,绑定的service也变为前台进程。 BIND_ALLOW_OOM_MANAGEMENT:允许系统在低内存等状态下删除该service。 BIND_WAIVE_PRIORITY:绑定service时不改变其优先级。 BIND_ADJUST_WITH_ACTIVITY:系统根据service所绑定的activity的重要程度来调整这个service的优先级。

Service和启动/绑定它的Activity是运行在一个进程/线程中吗?

如何在Service中下载图片?

需要在Service中新建线程,或使用IntentService。

什么是本地/全局/有序/粘性广播?

参看《广播组件》

介绍下常用的几种布局?

1、FrameLayout:所有东西依次都放在左上角,会重叠,这个布局比较简单,也只能放一点比较简单的东西。 2、LinearLayout:分为垂直布局和水平布局。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。 3、RelativeLayout:以某一个元素为参照物来定位的布局方式。 4、AbsoluteLayout:用X,Y坐标来指定元素的位置,这种布局方式也比较简单,但是在屏幕旋转时,往往会出问题,而且多个元素的时候,计算比较麻烦。不常用。 5、TableLayout:每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素。不常用。

如何写表格布局?

GridLayout/GridView

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

两种,一种是补间动画、一种是帧动画。补间动画是给出变化的初值和终值,以特定函数计算中间值生成动画;帧动画是通过顺序的播放排列好的图片来实现。

如何优化列表卡顿?

参看《实现列表》

RecyclerView和ListView的区别?

参看《实现列表》

介绍下Android的数据存储方式?

SharedPreferences存储数据:用来存储一些简单配置信息,采用了Map数据结构、以XML格式写入文件。 文件存储数据:可以直接用Java的I/O接口。 SQLite数据库存储数据; ContentProvider存储数据; 网络存储数据。

Intent的Flag有哪些?常用的应用场景有哪些?

FLAG_ACTIVITY_NEW_TASK:这个Activity会成为历史stack中一个新Task的开始。 FLAG_ACTIVITY_CLEAR_TOP:如果这个Activity已经在当前的Task中运行,因此,不再是重新启动一个这个Activity的实例,而是在这个Activity上方的所有Activity都将关闭,然后这个Intent会作为一个新的Intent投递到老的Activity(现在位于顶端)中(onNewIntent方法)。 FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET/FLAG_ACTIVITY_RESET_TASK_IF_NEEDED组合:前者在Task中设置一个还原点;当有Activity带着后者进入时,还原点和它之上都将关闭。 FLAG_ACTIVITY_SINGLE_TOP:这个Activity位于栈顶时,不再启动一个新的。 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:Activity不会在最近启动列表中保存。

注册广播有几种方式?

1、在清单文件中声明:常驻型,当应用程序关闭后也可接收到广播。 2、使用代码进行注册:不是常驻型,广播接收器跟随程序的生命周期。

解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系?

Handler获取当前线程中的looper对象,looper用来从MessageQueue中取出Message,再有Handler进行Message的分发和处理。

处理Message的优先级是怎样的?

1、Message里面的Callback,一个实现了Runnable接口的对象,其中run方法做处理工作; 2、Handler里面的mCallback,一个实现了Callback接口的对象,由其handleMessage进行处理; 3、Handler子类的实例,实现了其中handleMessage方法。

如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?

重写onSaveInstanceState()方法,在此方法中保存需要保存的数据,该方法将会在activity被回收之前调用。通过重写onRestoreInstanceState()方法可以从中提取保存好的数据。

如何安全退出已调用多个Activity的Application?

写一个Activity的管理类,用动态数组保存每个Activity的弱引用。

系统上安装了多种浏览器,能否指定某浏览器访问指定页面?

可以。通过直接发送Uri把参数带过去,或者通过manifest里的intentfilter里的data属性。

如何将SQLite数据库与apk一起发布?

可以将dictionary.db文件复制到res/raw目录中。所有在res/raw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。

如何打开res/raw目录中的数据库文件?

在Android中不能直接打开res/raw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。 复制的方法是使用getResources().openRawResource方法获得res/raw目录中资源的 InputStream对象,然后将该InputStream对象中的数据写入其他文件中。然后使用SQLiteDatabase.openOrCreateDatabase方法来打开文件。

哪些情况会引起内存泄漏?如何解决?

没有用的对象无法回收的现象就是内存泄露。 1、Activity作为参数构造单例模式 换成Application或Activity的弱引用作为参数。 2、Activity内有非静态内部类或匿名类,常见于AsyncTask或Handler 把AsyncTask或Handler声明为静态的。 3、对象被静态集合类引用 在使用完后及时调用clear() 4、需要手动关闭的对象没有关闭 网络、文件等流忘记关闭 手动注册广播时,退出时忘记 unregisterReceiver() Service 执行完后忘记 stopSelf() EventBus 等观察者模式的框架忘记手动解除注册

如果要加载一张很大的图,该怎么做?

1、图片压缩 先将BitmapFactory.Options的inJustDecodeBounds属性设置为true,解析一次图片,就可以得到原图的宽高。然后根据原图宽高和控件大小计算出合适的inSampleSize值。之后把inJustDecodeBounds设置为false,使用inSampleSize值再解析一次图片,就可以得到压缩后的Bitmap了。 2、图片缓存 BitmapPool、内存缓存、磁盘缓存 3、局部加载 BitmapRegionDecode

能通过指定包名的方法发送定向广播吗?

可以。 发送定向广播有2种方式。 1、发送广播时指定接收器的类。 2、注册接收器时为IntentFilter指定包名。

如何确定广播接收器的优先级?

1、在XML中设定receiver的优先级,数越大优先级别越高

<receiver android:name=".smsReceiver">
    <intent-filter android:priority="1000">
        <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
    </intent-filter>
</receiver>

2、调用IntentFilter对象的setPriority()进行设置 3、在相同优先级的情况下,动态注册优先级高于静态注册。在动态注册中,越早注册越高;在静态注册中,越早安装越高。

如何创建跨进程的Service?

详见《创建跨进程组件》,注意与“如何与Service通信”区分

你用Service做过什么?

文件上传下载。要重新开线程或使用IntentService。上传下载实现详见《使用Retrofit实现上传和下载》

你用广播做过什么?

1、Activity和Service通信 2、一个动作引起多个Activity中的UI元素变化的场景。比如用户更换头像

WRAP_CONTENT、MATCH_PARENT在onMeasure()中的实现有什么不同?

在确定子View的指导尺寸的过程中起作用。详见《View绘制》

重写onDraw()要注意什么?

1、不做耗时操作 2、尽量不创建新对象。因为onDraw()会被频繁调用

标签的作用是什么?

使用标签代替无用的父控件,减少控件树层级。比如Activity的顶级控件是FrameLayout时;自定义组合控件的顶级控件是无用的。

标签作用是什么?

为了复用已经存在的布局,不需要再写冗余的代码。与减少控件树层级无关。

Space为什么比空白View消耗少?

因为它的draw()方法为空

ViewStub的作用是什么?

惰性装载控件。ViewStub是一个无形的、零大小的视图,可以在程序运行的过程中,通过懒加载的模式inflate进布局资源中。当一个ViewStub的inflate()方法被调用或者被设为显示时,这个ViewStub使用设定的View才会被加载,并替换当前ViewStub的位置。因此,ViewStub存在于视图层次,直到setVisibility(int)或inflate()方法被调用,否则是不加载控件的,所以消耗的资源小。