大学姑娘是如何做到未毕业,就被BAT大厂高薪“抢人”只需这些题?

*   正如Fragment的名字“碎片”,它的出现是为了解决Android碎片化 ,它可作为Activity界面的组成部分,可在Activity运行中实现动态地加入、移除和交换。
*   一个Activity中可同时出现多个Fragment,一个Fragment也可在多个Activity中使用。
*   另外,Activity的**FragmentManager**负责调用队列中Fragment的生命周期方法,只要Fragment的状态与Activity的状态保持了同步,宿主Activity的FragmentManager便会继续调用其他生命周期方法以继续保持Fragment与Activity的状态一致。

Q:何时会考虑使用Fragment?

  • 技术点:Fragment作用
  • 思路:列举更适合使用Fragment的情况
  • 参考回答:非常经典的例子,即用两个Fragment封装两个界面模块,这样只使一套代码就能适配两种设备,达到两种界面效果;单一场景切换时使用Fragment更轻量化,如ViewPager和Fragment搭配使用

Q:谈一谈Service的生命周期?

  • 技术点:Service生命周期
  • 思路:分条解释Service从创建到销毁整个生命周期中涉及到的方法及作用
  • 参考回答:在Service的生命周期涉及到六大方法,分别是:
*   **onCreate()**:服务第一次被创建时调用
*   **onStartComand()**:服务启动时调用
*   **onBind()**:服务被绑定时调用
*   **onUnBind()**:服务被解绑时调用
*   **onDestroy()**:服务停止时调用
  • 引申:谈谈相对应的两种启动方式

Q:Service的两种启动方式?区别在哪?

  • 技术点:Service生命周期
  • 思路:分别解释两种启动模式如何启动和停止Service,并引起生命周期怎样的变化
  • 参考回答:
*   第一种,其他组件调用Context的 **startService()** 方法可以启动一个Service,并回调服务中的onStartCommand()。如果该服务之前还没创建,那么回调的顺序是onCreate()->onStartCommand()。服务启动了之后会一直保持运行状态,直到 **stopService()** 或 **stopSelf()** 方法被调用,服务停止并回调onDestroy()。另外,无论调用多少次startService()方法,只需调用一次stopService()或stopSelf()方法,服务就会停止了。
*   第二种,其它组件调用Context的 **bindService()** 可以绑定一个Service,并回调服务中的onBind()方法。类似地,如果该服务之前还没创建,那么回调的顺序是onCreate()->onBind()。之后,调用方可以获取到onBind()方法里返回的IBinder对象的实例,从而实现和服务进行通信。只要调用方和服务之间的连接没有断开,服务就会一直保持运行状态,直到调用了 **unbindService()** 方法服务会停止,回调顺序onUnBind()->onDestroy()。

Q:一个Activty先start一个Service后,再bind时会回调什么方法?此时如何做才能回调Service的destory()方法?

  • 技术点:Service生命周期
  • 参考回答:startService()启动Service之后,再bindService()绑定,此时只会回调onBind()方法;若想回调Service的destory()方法,需要同时调用 stopService()和 unbindService()方法才能让服务销毁掉。

Q:Service如何和Activity进行通信?

  • 技术点:Service信息传递
  • 思路:简单介绍Service如何和Activity双向通信的流程
  • 引申:谈谈底层的Binder机制

Q:用过哪些系统Service?

  • 技术点:Service类型(系统Service)
  • 参考回答:

Q:是否能在Service进行耗时操作?如果非要可以怎么做?

  • 技术点:Service使用注意
  • 参考回答:Service默认并不会运行在子线程中,也不运行在一个独立的进程中,它同样执行在主线程中(UI线程)。换句话说,不要在Service里执行耗时操作,除非手动打开一个子线程,否则有可能出现主线程被阻塞(ANR)的情况。
  • 引申:可以引申谈谈开子线程的几种方法

Q:AlarmManager能实现定时的原理?

  • 技术点:系统服务(后台定时)
  • 思路:AlarmManager
  • 参考回答:通过调用AlarmManager的 set() 方法就可以设置一个定时任务,并提供三个参数(工作类型,定时任务触发的时间,PendingIntent对象)。其中第三个PendingIntent对象是关键,一般会调用它的 getBroadcast() 方法来获取一个能够执行广播的PendingIntent。这样当定时任务被触发的时候,广播接收器的onReceive()方法就可以得到执行。即通过服务和广播的循环触发实现定时服务。
  • 引申:可谈谈底层定时机制实现原理

Q:前台服务是什么?和普通服务的不同?如何去开启一个前台服务?

  • 技术点:Service类型(前台Service)
  • 参考回答:和一般运行在后台的服务不同,前台服务的服务状态可以被用户一眼看到。它和普通服务最大的区别是,前者会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果,且当系统内存不足服务被杀死时,通知会被移除。实现一个前台服务也非常简单,和发送一个通知非常类似,只不过在构建好一个Notification之后,不需要NotificationManager将通知显示出来,而是调用了 startForeground() 方法。

Q:是否了解ActivityManagerService,谈谈它发挥什么作用?

  • 技术点:Service类型(ActivityManagerService)
  • 参考回答:ActivityManagerService是Android中最核心的服务 , 主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块类似。

Q:如何保证Service不被杀死?

  • 技术点:Service应用
  • 思路:列举几种解决办法
  • 参考回答:可以采取以下几种解决方法:
*   在Service的onStartCommand()中设置flages值为START\_STICKY,使得Service被杀死后尝试再次启动Service
*   提升Service优先级,比如设置为一个前台服务
*   在Activity的onDestroy()通过发送广播,并在广播接收器的onReceive()中启动Service

Q:广播有几种形式?什么特点?

  • 技术点:Broadcast类型
  • 思路:分条解释每种广播类型的特点
  • 参考回答:常见以下四种广播:
*   普通广播:一种**完全异步**执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们接收的先后是随机的。
*   有序广播:一种**同步执行**的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递,所以此时的广播接收器是有先后顺序的,且优先级(priority)高的广播接收器会先收到广播消息。有序广播可以被接收器截断使得后面的接收器无法收到它。
*   本地广播:发出的广播只能够在应用程序的**内部**进行传递,并且广播接收器也只能接收本应用程序发出的广播。
*   粘性广播:这种广播会一直滞留,当有匹配该广播的接收器被注册后,该接收器就会收到此条广播。

Q:广播的两种注册形式?区别在哪?

  • 技术点:Broadcast使用
  • 参考回答:广播的注册有两种方法:一种在活动里通过代码动态注册,另一种在配置文件里静态注册。两种方式的相同点是都完成了对接收器以及它能接收的广播值这两个值的定义;不同点是动态注册的接收器必须要在程序启动之后才能接收到广播,而静态注册的接收器即便程序未启动也能接收到广播,比如想接收到手机开机完成后系统发出的广播就只能用静态注册了。

Q:ContentProvider了解多少?

  • 技术点:ContentProvider
  • 思路:ContentProvider功能
  • 参考回答:作为四大组件之一,ContentProvider主要负责存储和共享数据。与文件存储、SharedPreferences存储、SQLite数据库存储这几种数据存储方法不同的是,后者保存下的数据只能被该应用程序使用,而前者可以让不同应用程序之间进行数据共享,它还可以选择只对哪一部分数据进行共享,从而保证程序中的隐私数据不会有泄漏风险。
  • 引申:谈谈ContentProvider底层使用Binder机制原理

Q:Android中提供哪些数据持久存储的方法?

  • 技术点:数据持久化
  • 思路:分条解释每种数据持久存储的特点
  • 参考回答:Android平台实现数据存储的常见几种方式:
*   File 文件存储:写入和读取文件的方法和 Java中实现I/O的程序一样。
*   SharedPreferences存储:一种轻型的数据存储方式,常用来存储一些简单的配置信息,本质是基于XML文件存储key-value键值对数据。
*   SQLite数据库存储:一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,在存储大量复杂的关系型数据的时可以使用。
*   ContentProvider:四大组件之一,用于数据的存储和共享,不仅可以让不同应用程序之间进行数据共享,还可以选择只对哪一部分数据进行共享,可保证程序中的隐私数据不会有泄漏风险。

Q:Java中的I/O流读写怎么做?

  • 技术点:数据持久化(文件存储)
  • 思路:大致介绍核心类和核心方法
  • 参考回答:和 Java中实现I/O的程序是一样的,Context类中提供了openFileInput()和openFileOutput()方法来打开数据文件里的文件IO流,有关读写涉及的主要方法详见文章学习笔记| AS入门(七) 数据存储篇

Q:SharePreferences适用情形?使用中需要注意什么?

  • 技术点:数据持久化(SharePreferences存储)
  • 参考回答:SharePreferences是一种轻型的数据存储方式,适用于存储一些简单的配置信息,如int、string、boolean、float和long。由于系统对SharedPreferences的读/写有一定的缓存策略,即在内存中有一份该文件的缓存,因此在多进程模式下,其读/写会变得不可靠,甚至丢失数据。
  • 引申:谈谈Android中多进程通信(Binder)

Q:了解SQLite中的事务处理吗?是如何做的?

  • 技术点:数据持久化(SQLite)
  • 参考回答:SQLite在做CRDU操作时都默认开启了事务,然后把SQL语句翻译成对应的SQLiteStatement并调用其相应的CRUD方法,此时整个操作还是在rollback journal这个临时文件上进行,只有操作顺利完成才会更新.db数据库,否则会被回滚。
  • 引申:谈谈如何模仿SQLite中事务的思想更高效进行批量操作

Q:使用SQLite做批量操作有什么好的方法吗?

  • 技术点:数据持久化(SQLite)
  • 思路:模仿SQLite的事务处理
  • 参考回答:使用SQLiteDatabase的beginTransaction()方法开启一个事务,将批量操作SQL语句转化成SQLiteStatement并进行批量操作,结束后endTransaction()

Q:如果现在要删除SQLite中表的一个字段如何做?

  • 技术点:数据持久化(SQLite)
  • 参考回答:SQLite数据库只允许增加表字段而不允许修改和删除表字段,只能采取复制表思想,即创建一个新表保留原表想要的字段、再将原表删除

Q:使用SQLite时会有哪些优化操作?

  • 技术点:数据持久化(SQLite)
  • 思路:列举可优化点
  • 参考回答:
*   使用事务做批量操作:具体操作见上
*   及时关闭Cursor,避免内存泄漏
*   耗时操作异步化:数据库的操作属于本地IO,通常比较耗时,建议将这些耗时操作放入异步线程中处理
*   ContentValues的容量调整:ContentValues内部采用HashMap来存储Key-Value数据,ContentValues初始容量为8,扩容时翻倍。因此建议对ContentValues填入的内容进行估量,设置合理的初始化容量,减少不必要的内部扩容操作
*   使用索引加快检索速度:对于查询操作量级较大、业务对要求查询要求较高的推荐使用索引

Q:Android中进程和线程的关系?

  • 技术点:进程、线程
  • 参考回答:
*   形象理解:如果把安卓系统比喻成一片土壤,可以把App看做扎根在这片土壤上的工厂,每个APP一般对应一个进程,那么线程就像是工厂的生产线。其中,主线程好比是主生产线,只有一条,子线程就像是副生产线,可以有很多条。
*   关系:一个APP一般对应一个进程和有限个线程
    *   一般对应一个进程,当然,可以在AndroidMenifest中给四大组件指定属性`android:process`开启多进程模式
    *   有限个线程:线程是一种**受限**的系统资源,不可无限制的产生且线程的创建和销毁都有一定的开销。

Q:为何需要进行IPC?多进程通信可能会出现什么问题?

  • 技术点:多进程通信
  • 思路:讨论多进程通信会出现的问题得出IPC的必要性
  • 参考回答:
  • (1)多进程造成的影响可总结为以下四方面:
*   静态变量和单例模式失效:由独立的虚拟机造成
*   线程同步机制失效:由独立的虚拟机造成
*   SharedPreference的不可靠下降:不支持两个进程同时进行读写操作,即不支持并发读写,有一定几率导致数据丢失
*   Application多次创建: Android系统会为新的进程分配独立虚拟机,相当于系统又把这个应用重新启动了一次。
  • (2)需要进程间通信的必要性:所有运行在不同进程的四大组件,只要它们之间需要通过内存在共享数据,都会共享失败。这是由于Android为每个应用分配了独立的虚拟机,不同的虚拟机在内存分配上有不同的地址空间,这会导致在不同的虚拟机中访问同一个类的对象会产生多份副本。
  • 引申: 谈谈IPC的使用场景

Q:Android中为何新增Binder来作为主要的IPC方式?

  • 技术点:Binder机制
  • 思路:回答Binder优点
  • 参考回答:Binder机制有什么几条优点
*   传输效率高、可操作性强:传输效率主要影响因素是内存拷贝的次数,拷贝次数越少,传输速率越高。从Android进程架构角度分析:对于消息队列、Socket和管道来说,数据先从发送方的缓存区拷贝到内核开辟的缓存区中,再从内核缓存区拷贝到接收方的缓存区,一共两次拷贝,如图:

而对于Binder来说,数据从发送方的缓存区拷贝到内核的缓存区,而接收方的缓存区与内核的缓存区是映射到同一块物理地址的,节省了一次数据拷贝的过程,如图:

Q:使用Binder进行数据传输的具体过程?

  • 技术点:Binder机制

  • 思路:通过AIDL实现方式解释Binder数据传输的具体过程

  • 参考回答:服务端中的Service给与其绑定的客户端提供Binder对象,客户端通过AIDL接口中的asInterface()将这个Binder对象转换为代理Proxy,并通过它发起RPC请求。客户端发起请求时会挂起当前线程,并将参数写入data然后调用transact(),RPC请求会通过系统底层封装后由服务端的onTransact()处理,并将结果写入reply,最后返回调用结果并唤醒客户端线程。

Q:Binder框架中ServiceManager的作用?`

  • 技术点:Binder机制

  • 思路:从Binder框架出发讨论每个元素的作用

  • 参考回答:在Binder框架定义了四个角色:Server,Client,ServiceManager和Binder驱动。其中Server、Client、ServiceManager运行于用户空间,Binder驱动运行于内核空间。关系如图:

  • Server&Client:服务器&客户端。在Binder驱动和Service Manager提供的基础设施上,进行Client-Server之间的通信。

  • ServiceManager服务的管理者,将Binder名字转换为Client中对该Binder的引用,使得Client可以通过Binder名字获得Server中Binder实体的引用。流程如图:

Binder驱动:

与硬件设备没有关系,其工作方式与设备驱动程序是一样的,工作于内核态。

提供open()、mmap()、poll()、ioctl() 等标准文件操作。

以字符驱动设备中的misc设备注册在设备目录/dev下,用户通过/dev/binder访问该它。

负责进程之间binder通信的建立,传递,计数管理以及数据的传递交互等底层支持。

驱动和应用程序之间定义了一套接口协议,主要功能由ioctl() 接口实现,由于ioctl()灵活、方便且能够一次调用实现先写后读以满足同步交互,因此不必分别调用write()和read()接口。

其代码位于linux目录的drivers/misc/binder.c中。

Q:Android中有哪些基于Binder的IPC方式?简单对比下?

  • 技术点:IPC方式

  • 思路:分析每种IPC方式的优缺点和使用场景的差异

  • 参考回答:

Q:MotionEvent是什么?包含几种事件?什么条件下会产生?

  • 技术点:View触控
  • 参考回答:MotionEvent是手指触摸屏幕锁产生的一系列事件。包含的事件有:
*   **ACTION\_DOWN**:手指刚接触屏幕
*   **ACTION\_MOVE**:手指在屏幕上滑动
*   **ACTION\_UP**:手指在屏幕上松开的一瞬间
*   **ACTION\_CANCEL**:手指保持按下操作,并从当前控件转移到外层控件时会触发

Q:scrollTo()和scrollBy()的区别?

  • 技术点:View滑动
  • 参考回答:scrollBy内部调用了scrollTo,它是基于当前位置的相对滑动;而scrollTo是绝对滑动,因此如果利用相同输入参数多次调用scrollTo()方法,由于View初始位置是不变只会出现一次View滚动的效果而不是多次。
  • 引申:两者都只能对view内容进行滑动,而不能使view本身滑动,且非平滑,可使用Scroller有过渡滑动的效果

Q:谈一谈View的事件分发机制?

  • 技术点:View事件分发
  • 思路:从分发本质、传递顺序、核心方法展开
  • 参考回答:
*   事件分发本质:就是对**MotionEvent事件**分发的过程。即当一个MotionEvent产生了以后,系统需要将这个点击事件传递到一个具体的View上。
*   点击事件的传递顺序:**Activity(Window) -> ViewGroup -> View**
*   三个主要方法:
    *   **dispatchTouchEvent**:进行事件的分发(传递)。返回值是 boolean 类型,受当前onTouchEvent和下级view的dispatchTouchEvent影响
    *   **onInterceptTouchEvent**:对事件进行拦截。该方法只在ViewGroup中有,View(不包含 ViewGroup)是没有的。一旦拦截,则执行ViewGroup的onTouchEvent,在ViewGroup中处理事件,而不接着分发给View。且只调用一次,所以后面的事件都会交给ViewGroup处理。
    *   **onTouchEvent**:进行事件处理。

Q:如何解决View的滑动冲突?

  • 技术点:View滑动冲突
  • 思路:从处理规则和具体实现方法展开讨论
  • 参考回答:
  • (1)处理规则:
*   对于由于外部滑动和内部滑动**方向不一致**导致的滑动冲突,可以根据滑动的方向判断谁来拦截事件。
*   对于由于外部滑动方向和内部滑动**方向一致**导致的滑动冲突,可以根据业务需求,规定何时让外部View拦截事件何时由内部View拦截事件。
*   对于上面两种情况的嵌套,相对复杂,可同样根据需求在业务上找到突破点。
  • (2)实现方法:
*   **外部拦截法**:指点击事件都先经过**父容器的拦截处理**,如果父容器需要此事件就拦截,否则就不拦截。具体方法:需要重写父容器的**onInterceptTouchEvent**方法,在内部做出相应的拦截。
*   **内部拦截法**:指父容器不拦截任何事件,而将所有的事件都传递给子容器,如果子容器需要此事件就直接消耗,否则就交由父容器进行处理。具体方法:需要配合**requestDisallowInterceptTouchEvent**方法。

Q:onTouch()、onTouchEvent()和onClick()关系?

  • 技术点:View事件分发
  • 参考回答:优先度onTouch()>onTouchEvent()>onClick()。因此onTouchListener的onTouch()方法会先触发;如果onTouch()返回false才会接着触发onTouchEvent(),同样的,内置诸如onClick()事件的实现等等都基于onTouchEvent();如果onTouch()返回true,这些事件将不会被触发。

Q:SurfaceView和View的区别?

  • 技术点:View、SurfaceView
  • 参考回答:SurfaceView是从View基类中派生出来的显示类,他和View的区别有:
*   View需要在UI线程对画面进行刷新,而SurfaceView可在子线程进行页面的刷新
*   View适用于主动更新的情况,而SurfaceView适用于被动更新,如频繁刷新,这是因为如果使用View频繁刷新会阻塞主线程,导致界面卡顿
*   SurfaceView在底层已实现双缓冲机制,而View没有,因此SurfaceView更适用于需要频繁刷新、刷新时数据处理量很大的页面

Q:invalidate()和postInvalidate()的区别?

  • 技术点:View刷新
  • 参考回答:invalidate()与postInvalidate()都用于刷新View,主要区别是invalidate()在主线程中调用,若在子线程中使用需要配合handler;而postInvalidate()可在子线程中直接调用。

Q:了解哪些Drawable?适用场景?

  • 技术点:res资源
  • 参考回答:BitmapDrawable表示一张图片、NinePatchDrawable可自动地根据所需的宽/高对图片进行相应的缩放并保证不失真、ShapeDrawable表示纯色、有渐变效果的基础几何图形、StateListDrawable表示一个Drawable的集合且每个Drawable对应着View的一种状态、LayerDrawable可通过将不同的Drawable放置在不同的层上面从而达到一种叠加后的效果

Q:mipmap系列中xxxhdpi、xxhdpi、xhdpi、hdpi、mdpi和ldpi存在怎样的关系?

  • 技术点:res资源
  • 参考回答:表示不同密度的图片资源,像素从高到低依次排序为xxxhdpi>xxhdpi>xhdpi>hdpi>mdpi>ldpi,根据手机的dpi不同加载不同密度的图片

Q:dp、dpi、px的区别?

  • 技术点:Android适配
  • 参考回答:
*   px:像素,如分辨率1920x1080表示高为1920个像素、宽为1080个像素
*   dpi:每英寸的像素点,如分辨率为1920x1080的手机尺寸为4.95英寸,则该手机DPI为(1920x1920+ 1080x1080)½/4.95≈445dpi
*   dp:密度无关像素,是个相对值

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

更多学习和讨论,欢迎加入我们!

有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

这里有2000+小伙伴,让你的学习不寂寞~·

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

外链图片转存中…(img-E4enaPFJ-1713541993177)]

[外链图片转存中…(img-IPZcGklB-1713541993178)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

[外链图片转存中…(img-YIqFaD9k-1713541993180)]

更多学习和讨论,欢迎加入我们!

有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

这里有2000+小伙伴,让你的学习不寂寞~·

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值