1、Listener和Callback的区别
Listener和Callback都是观察者模式的实现方式,但其概念上存在一些区别。
Listener一般指的是事件监听器,是一种被动的观察者模式,其作用是等待某个事件的发生,然后被回调处理。在Android中,UI事件的回调就是使用Listener方式实现的,例如Buttin的OnClickListener。
Callback可以理解为回调函数,是一种主动的观察者模式,其作用是在某些情况下主动触发某个处理过程。在Android中,AsyncTask就是使用Callback方式实现的,当异步任务完成后,会主动回调onPostExecute方法。
2、Stub和Proxy的区别
在Android中,Stub和Proxy都是代理模式的实现,它们通常用于实现进程间通信(IPC,如Binder)和远程过程调用(RCP),但它们的代理对象不同。
Stub(存根)是服务器和客户端之间的代理,负责将客户端的请求传递给服务器端。它类似于一个代理对象,负责完成一些远程调用的功能。客户端本身不直接调用服务器端,而是通过Stub进行调用。Stub被视为客户端和服务器之间的桥梁,它隐藏了底层的通信细节。
Proxy(代理)是客户端的本地代理,它代表了远程对象,用于向客户端提供远程对象的访问接口。它覆盖了底层的通信细节,使客户端可以像本地对象一样访问远程对象。Proxy对象在客户端上创建,并将客户端的请求转发给Stub对象处理。
Proxy 相当于是拿在手里的遥控器,而 Stub 相当于长在电视机里的遥控接收器,它们有着一一对应的接口方法,但操作的方向刚好相反。Proxy 的接口供客户端程序调用,然后它内部会把信息包装好,以某种方式(比如 RMI)传递给 Stub,而后者通过对应的接口作用于服务端系统,从而完成了“远程调用”。
Stub 跟 Proxy 是一对,俗称“代理-桩”,一般用在远程方法调用。一般不同进程间通信的时候都会用到这种模式。
参考: AIDL过程分析 | Wiki - PingCode
3、Thread和Runnable的区别
在Andrid中,Thread和Runnable都是用来创建新线程的方法,但是它们的实现方式有很多的区别。
Thread是一个类,它继承自Java的Thread类,使用Thread创建新线程的方式是继承Thread类,然后重写run()方法,在run()方法中定义线程要执行的代码。线程启动的时候,调用Thread的start()方法。
Runnable是一个接口,它定义了线程要执行的任务,使用Runable创建新线程的方式是创建一个Runnable实例,然后将它作为参数传递给Thread的构造方法。
所以,Runnable是一种更加灵活的方式,因为它可以很容易地实现多个接口,从而实现多个任务的执行。另外,由于Java只支持单继承,如果一个类已经继承了其他类,就无法再继承Thread类了,这时候就只能使用Runnable接口了。
总统来说,Thread是一种更加简单的方式,适合简单任务的执行;而Runnable是一种更加灵活的方式,适合复杂任务的执行。在Android开发中,推荐使用Runable来创建新线程。
4、Thread、Handler、MessageQueue、Message、Looper关系
在Android中,Thread、Handler、MessageQueue、Message、Looper是属于Android多线程机制的一部分,它们之间的关系如下:
Thread是操作系统层面的线程,它用于执行耗时操作或者需要对UI进行操作的任务。
Handler是用于线程间的通信,它可以将消息(Message)发生到MessageQueue中,然后在指定的线程中接收并处理这些消息。
MessageQueue是用于储存消息的队列,每个线程都有一个MessageQueue,用于存储等待处理的消息。
Message用于在线程之间传递消息,它包含了一些需要传递的信息以及Handler对象。
Looper是用于循环读取MessageQueue中的消息并将它们交给Handler来处理的对象,它只能存在一个线程中,通常是主线程。
Message是承载任务的载体,在Handler机制中贯穿始终,Handler则是对外公开的API,负责发送Message和处理任务的回调,是Message的生产者,Message负责管理待处理Message的入队和出队,是Messae的容器,Looper负责轮循MessageQueue,保持线程持续运行任务,是Message的消费者。
因此,当我们在一个线程中使用了Handler,他会向该线程的MessageQueue中发生消息,然后由Looper在该线程中循环读取该MessageQueue中的消息,并将消息交给Handler来处理。这些机制使得我们可以很方便地实现线程间得通信和操作UI等操作。
5、Thread、Runable、HandlerThread、AsyncTask的区别
Thread是Java中的基本类,可以通过继承Thread类或实现Runnable接口来创建线程。Thread在Android中也可以使用,但由于Android需要保持应用程序的响应速度、不建议在UI线程只外创建太多的线程。
Runable同Thread一样,也可以让线程并发执行函数,但是与Thread不同的是,一个线程可以有多个Runnable。Runnable被ThreadPoolExecutor(线程池)类广泛使用,因为它们可以避免大量创建和终止线程时出现的开销。
HanderThread用于简化线程中消息的处理,它是Thread的子类,它提供了一个消费者调度机制,可以使用其中的Looper在执行发送到队列中的消息时间死循环。创建HandlerThread时默认会创建一个Looper,通过这个Looper创建出的Handler可在这个Looper所在的线程中处理消息。
AsyncTask是必须由UI线程中拥有,以便继续在背景线程中执行任务而不冻结UI线程。它使开发者可以在像UI线程之外的后台线程中轻松执行异步操作。它包含对线程池的支持,以便在多个异步任务依次运行时共享基础线程。它也支持线程的优先级和取消功能。从Android11(API level30)开始,AsyncTask已经被标记为“过时”,这意味着它已不建议在新的Android应用程序中使用。
总结:Thread和Runnable是用于基本线程创建和管理的。HandlerThread是用于线程间通信。AsyncTask是为了进行异步任务处理,与UI线程无缝协作。
6、ReentrantLock和Synchronized区别
ReentrantLock和Synchronize都可以用于保护共享资源使其在多线程环境下安全访问,但它们有以下不同之处。
-
锁的释放方式不同:ReentrantLock需要手动释放锁,而Synchronize在代码块执行完成或者抛出异常时自动释放锁。
-
可重入性:Synchronize是可重入锁,同一线线程可以重复获取同一个锁。而ReentrantLock也是可重入锁,但需要手动调用lock()和unlock()方法来保证同步代码的正确性。
-
公平性:ReentrantLock可以设置公平锁或非公平锁,而Synchronize只能是非公平锁(公平锁的意思是若存多个等待获取锁的线程,谁等待的时间越来就先获取到锁)。
-
等待可中断:ReentrantLock提供了一个lockInterruptibly()方法,允许等待获取锁的线程在等待过程中被中断,而Synchronize不支持线程中中断操作,一点进入等待状态,就必须等待获取锁。
-
条件变量:ReentrantLock支持多个Condition(条件变量),可以让线程按照条件来等待和唤醒。而Synchronize只能使用wait()和notify()方法,不能自定义多个条件变量。
-
性能:Synchronized是JVM级别的锁,不需要额外的资源开销,但是效率稍低。而ReentrantLock是JDK级别的锁,需要自己管理锁的获取和释放,加锁和解锁的开销较大。但是当高并发访问的时候,ReentrantLockd的表现要优于Synchronized。
综上所述,Synchronized是一种简单、易用、线程安全的锁,而ReentrantLock则是一种功能更加强大、灵活性更高、性能更优的锁。由于ReentrantLock在某些方面更加高级和灵活,因此在复杂的并发场景中,一般更容易使用。
7、notify方法和notifyAll方法的区别
notify只能唤醒一个线程,notifyAll可以唤醒所有等待的线程。
notify可能出现假死的情况,即唤醒线程对共享资源操作后,其他线程还是无法获得锁,仍然处于等待状态。而notifyAll不会出现这种情况,因为它会唤醒所有线程,让它们重新竞争执行。
因此,当有多个线程等待共享资源时,通常使用notifyAll方法,以确保所有线程都能够得到执行的机会。
8、ViewRootImpl和DecorView的区别
ViewRootImpl是View层级结构和窗口管理的关键类,它作为View树和WindowManager之前的桥梁,负责将应用程序的View树描绘到屏幕上。而DecorView是View层次结构中的顶级视图,作为窗口中主要承载app UI的容器,可以接受和处理用户的输入事件。
ViewRootImpl是在Activity启动时由WindowManagerService负责创建和管理的,其生命周期同Activity一致。而DecorView是在Activity的setContentView()方法执行时由ActivityThread调用PhoneWindow的installDecor()方法创建的,表示整个应用窗口的根视图,其生命周期也随Activity的生命周期而变化。
ViewRootImpl主要负责在屏幕上渲染app UI,并通过SurfaceFlinger将UI绘制到硬件屏幕上。DecorView则负责管理View层次结构、测量和布局、绘制和事件分发等操作,并为用户提供界面显示和交互。
Activity启动过程中,系统会创建ViewRootImpl实例,并将DecorView添加到ViewRootImpl中进行绘制。
9、Window与View的区别‘
Window是Android系统中表示屏幕窗口的概念,它是View层级结构的最上层,负责管理View的绘制和显示。每个Activity都有一个Window对象,用于显示Activity中的UI。
View是一种UI控件,用于在屏幕上显示的接收用户输入操作。View是Android UI的基础构建块,所有的UI控件都是从View派生来的,例如Button、TextView、ImageView等待。
总体来说,View是一个UI组件,而Window是用户管理和显示View的概念。它们有很强的关联,但是又有着不同的作用和职责。
10、PhoneWindow和DecorView的区别
PhoneWindow是一个特殊的Window,用于在屏幕中显示应用程序界面。它是一个顶级的窗口,用户管理应用程序的整个窗口装饰和布局。PhoneWindow承载着DecorView,就像Activity承载着VIew。
DecorView是PhoneWindow内部的一个ViewGroup,用于承载应用程序的所有View。它是PhoneWindow中的最顶层布局,负责应用程序的窗口装饰,包括标题栏、状态栏、导航栏等。DecorView是Android中最重要的View之一,可以通过setContentView()方法向其添加应用程序的布局。
11、IWindow和IWindowManager的区别
IWindow和IWindowManager接口都是Android系统钟重要的接口,但二者的职责不同。
IWindow接口位于Android系统的ViewRootImpl类中,负责管理单个窗口的生命周期、布局和绘制等。每个窗口都有一个对应的ViewRootImpl实例,它实现了IWindow接口,提供了一系列方法用于处理窗口的显示和输入事件。IWindow接口中的方法包括:
-
dispatchinputEvent:分发输入事件至窗口。
-
executeCommand:执行窗口命令。
-
resized:窗口大小改变时的回调。
-
windowFocusChanged:窗口焦点状态改变时的回调。
与之对比,IWindowManager接口是Android系统中的系统服务,用于管理多个窗口的创建、销毁、移动和调整大小等操作。IWindowManager接口中的方法包括:
-
addWindow:在屏幕上添加一个新窗口。
-
removeWindow:从屏幕上删除一个现有窗口。
-
setWindowToken:设置窗口标识。
-
updateWindowLayout:更新窗口布局。
因此可以看出,IWindow接口是用户管理单个窗口的接口,而IWindowManager接口则是管理多个窗口的接口。在Android系统中,IWindow和IWindowManager之间存在一定的关系,IWindow负责处理特定窗口的事件,而IWindowManager则负责协调多个窗口的显示和交互。
12、WindowManager与PhoneWindowManager的区别
WindowManager是Android系统中的一个服务(WindowManagerService),它负责管理应用程序的窗口,提供了创建、移动、调整大小等窗口操作API,同时也负责处理用户交互事件,如触摸、按键等操作。
PhoneWindowManager则负责实现WindowManagerPolicy接口中定义的方法,它是WindowManager的策略实现类,负责更细粒度的处理窗口和用户交互事件。
WindowManager与PhoneWindowManager之间是一种组合、依赖的关系。PhoneWindowManager作为WindowManager的策略实现类,提供了更细粒度的处理方法和具体实现,与WindowManager一起维护整个窗口和用户交互的机制。
13、perform和handle的区别
perform前缀通常表示方法时用来执行某个操作的,例如,performClick()方法用于执行一个UI元素的点击操作,performResume()方法用于执行一个Activity的恢复操作,这些方法一般返回一个boolean值,用于表示操作是否成功。
handle前缀通常方法是用来处理某个事件或消息的,例如,handleMessage()方法用于处理消息,handleIntent()方法用于处理Intent,这些方法一般没有返回值,而是通过调用其他的方法或发送广播等方式完成相应的操作。
perform表示执行某个操作,一般用于UI元素或者Activity等的操作,而handle表示处理某个事件或消息,一般用于处理消息、intent等事件。
14、IWindow、IWindowId、IWindowSession、IWindowSessionCallback、IWindowFocusObserver、IWindowManager的区别
15、Bn和Bp的区别
Bn和Bp是Android RPC(Remote Procedure Cll)框架中的两个关键类,分别用于客户端和服务端的通信和传输。
Bn表示Binder Native,是一个本地Binder通信的基础类,主要提供了客户端和服务端之间数据交换的接口。它是Binder通信的底层核心,实现了IPC的基本操作,比如协议的序列化和反序列化、缓存数据的管理、连接的创建和维护等。在客户端和服务端之间进行通信时,客户端因为想要访问服务端的某个方法,而要通过Bn类进行方法调用、消息传递等操作。
Bp表示Binder Proxy,是客户端调用服务端的代理类。Bp类使得客户端可以直接向服务端发送请求,从而实现RPC调用。当客户端调用服务端的某个方法时,实际上是通过Bp类创建一个Binder对象,并将该对象发送到服务端,服务端根据该对象的标识符识别客户端的请求,并处理相应的业务逻辑。Bp类实现了IBinder接口和IInterface接口,并通过重写onTransact方法等方式,实现了客户端和服务端的交互。
如下为ServiceManager中Bp和Bn的关系:

16、音频会话和音频焦点的区别
音频会话(AudioSession)是Android中用于表示应用程序中特定音频流的抽象概念。每一个音频会话都包含了一组音频属性,用于描述当前正在播放的音频流的内容和特性,例如采样率、通道数、编码格式、媒体格式、媒体类型等等。开发人员可以利用音频会话来控制应用程序内部的音频流播放,并可通过AudioManager获取当前活动的音频会话列表。
音频焦点(AudioFocus)则是值Audio中通过音频系统来管理各种应用程序之间的音频播放。在Android中,默认情况下同一时间只有一种应用程序或服务能够获得系统的音频焦点,而其他的应用程序则被迫停止或暂停音频播放。通过音频焦点机制,应用程序可以协调不同的音频播放请求,以避免音频播放产生的冲突和干扰。
17、wait、waitRelative、signal、broadcast区别
-
status_t wait(Mutex& mutex);
-
status_t waitRelative(Mutex& mutex, nsecs_t reltime);
-
void signal();
-
void broadcast();
wait() 等待条件变量(Condition Variable)
Mutex作为参数,调用该函数之前该MUTEX必须已经被lock住。
执行该函数,会unlock该MUTEX,并等待条件变量。如果不能获得该条件变量,就被挂起等待;获得了该条件变量,就重新lock住MUTEX并返回。而这些操作都是原子操作的。
该函数执行之后,Mutex被重新lock住,所以执行函数之后,必须有Mutex的unlock操作。
waitRelative()与和wait()的区别是,会有一个等待超时时间,到了时间没有获得该条件变量也会返回,可通过返回值判断结果。
signal()和broadcast() 触发条件变量(Condition Variable)
signal()和broadcast() 的区别是,signal()只允许等待该条件变量的一个线程获得;broadcast()允许等待该条件变量的所有线程获得并继续执行。
signal()和broadcast() 执行之前也必须lock住Mutex,执行之后unlock Mutex。

1615

被折叠的 条评论
为什么被折叠?



