Android笔记
1,AIDL每次传输数据大小,应小于()
答:受限于Android本身对AIDL的设计,利用AIDL传输的数据大小不得大于1MB,否则会报TransactionTooLargeException。
2,屏幕事件的分发,可以通过()方法,返回()拦截此次事件,拦截后此次事件不再向子View传递
答:事件分发中科院用过onInterceptTouchEvent方法,返回为true拦截此次事件,不再向子view传递
3,git pull命令相当于get fetch与git()命令的组合
答:git merge
4,为了灵活搭配参数,可以使用()设计模式
答: 建造者模式
5,一个未启动的serviceA,先通过startService启动,再通过bindservice启动,生命周期函数调用执行顺序如下()
答:onCreate-->onStartCommand-->onStart-->onBind-->(onServiceConnected)
6,进程间数据交互有哪些方法()
答:使用Bundle,使用AIDL,使用ContentProvider
7,Android自动化测试框架是(至少两种)()
答:Monkey,MonkeyRunner,UIAutomator,Robotium,Appium,Instrumentation,Espresso,Selendroid
8,Android中常见的TweenAnimation-补间动画,有哪些?至少答出两种
答:平移动画:<translate> TranslateAnimation
缩放动画:<scale> ScaleAnimation
旋转动画:<rotate> RotateAnimation
透明度动画:<alpha> AlphaAnimation
9,MMKV和SharedPreference类似都是一种()存储
答:轻量级
10,在自定义动画中,一般采用()来控制动画变化的速率
答:动画插值器,Timelnterpolator
11,一个线程最多有()个looper和()个messageQueue
答:一个线程可以有多个Handler,只有一个Looper,只有一个MessageQueue。多个Handler共用一个Looper和MessageQueue。
12,使用SharePreference保存数据,调用()接口可以做到同步存储数据
答:commit()方法可以同步保存数据
apply()方法为异步保存数据
13,ARGB_4444每个像素占用()内存
答:理论上图片占用内存计算:图片占用内存=宽度像素高度像素单个像素占的字节数。
Android中的四个色彩模式:
ALPHA_8:每个像素占用1byte内存
ARGB_4444:每个像素占用2byte内存
ARGB_8888:每个像素占用4byte内存
RGB_565:每个像素占用2byte内存
14,通过adb链接设备后,可以通过什么指令来查看包名com.mxnavi.sampie应用的详细内存信息()
答:adb shell dumpsys meminfo com.mxnavi.sampie
15,主线程出现ANR异常,出现anr之后,由()会输出一个trace文件到()目录。
答:出现ANR系统会输出一个trace.txt文件,目录在/data/anr中
16,在ActivityA中启动一个未启动过的ActivityB执行生命周期函数的顺序应该为()
答:a. A-onCreate()
b. A-onStart()
c. A-onResume()
----启动B----
d. A-onPause()
e. B-onCreate()
f. B-onStart()
g. B-onResume()
h. A-onStop()
17,为了防止横竖屏切换时,Activity不重新创建,需要在AndroidManifest()属性中,增加()配置
答:需要在manifest中配置 android:configChanges="orientation|keyboardHidden"属性,当然在api>13的时候,需要额外添加一个参数,就是 screenSize ,不添加这个,在api 13以上的手机是不会生效的。
18,当我们要制作一个可以横向滚动的超屏布局时,需要使用()布局View来实现
答:HorizontalScrollView 和 ScrollView 都是由 FrameLayout 派生出来的。它们就是一个用于为普通组件添加滚动条的组件。且 HorizontalScrollView 和 ScrollView 里面最多只能包含一个组件(当然组件里面还可以嵌套组件)。它们不同的是 HorizontalScrollView 用于添加水平滚动,而 ScrollView 用于添加垂直滚动。
19,如何通过git命令合并两次提交,要求change id 不变()
答:区分两个场景
- 第二次commit之前提交,当第一次push之后
step1.vi new_add.txt添加新的文件
step2.git add new_add.txt
step3.git commit --amend把文件和上一次提交合并
step4.git pus origin HEAD:refs/for/$branch - 第二次commit之后提交,当第二次提交已经执行了push之后,发现生成了两个change-Id
step1.查看提交历史记录,git log
step2.选择要合并的commit,“2”代表要合并最新的3条commit
git rebase -i HEAD~2
step3.修改要保留的commit和要合并的commit
pick代表选择这个commit,squash代表合并这个commit或者用s也可以
step4.修改commit的文字描述。不需要的commit描述也注释掉
step5.git push origin xxxx -f
20,自定义View可以通过重写()方法获得Canvas
答:重写onDraw()
问答题
21,写一个简单的线程池,(不适用线程池API),包括线程管理,任务管理,线程池大小可设置。
/**
* 自定义简单线程池
*/
public class MyThreadPool{
/**存放线程的集合*/
private ArrayList<MyThead> threads;
/**任务队列*/
private ArrayBlockingQueue<Runnable> taskQueue;
/**线程池初始限定大小*/
private int threadNum;
/**已经工作的线程数目*/
private int workThreadNum;
private final ReentrantLock mainLock = new ReentrantLock();
public MyThreadPool(int initPoolNum) {
threadNum = initPoolNum;
threads = new ArrayList<>(initPoolNum);
//任务队列初始化为线程池线程数的四倍
taskQueue = new ArrayBlockingQueue<>(initPoolNum*4);
threadNum = initPoolNum;
workThreadNum = 0;
}
public void execute(Runnable runnable) {
try {
mainLock.lock();
//线程池未满,每加入一个任务则开启一个线程
if(workThreadNum < threadNum) {
MyThead myThead = new MyThead(runnable);
myThead.start();
threads.add(myThead);
workThreadNum++;
}
//线程池已满,放入任务队列,等待有空闲线程时执行
else {
//队列已满,无法添加时,拒绝任务
if(!taskQueue.offer(runnable)) {
rejectTask();
}
}
22,简述SurfaceView双缓冲机制
答:SurfaceView的双缓冲机制是为了防止闪烁和卡顿现象。在绘制过程中,通常会发生不可避免的计算机IO延迟,这可能会导致屏幕绘制停顿。
如果没有双缓冲机制,在主线程更新UI的同时,绘制的结果也将立即呈现在前台界面上,这可能导致视觉上的不连续性和闪烁。
双缓冲机制会维护两个Surface对象,一个在前台,呈现在屏幕上,另一个在后台,后台绘制,在绘制之前,将要绘制的内容先绘制到后台Surface上,然后前后交换两个Surface,这样前台Surface就显示了最新的绘制结果。
整个缓冲机制的过程如下:
- 创建两个Surface对象,分别是前台和后台surface
- 获取后台surface上的canvas对象
- 在canvas对象上绘制要显示的内容
- 将后台surface上的内容复制到前台surface
- 显示前台surface上的内容
23,在自定义View中,除了构造函数需要重写的方法有哪三个,分别的作用是什么?
答:测量:onMeasure(),作用决定了View的大小
布局:onLayout(),作用决定View在ViewGruop中的位置
绘制:onDraw(),作用决定绘制View
24,AIDL是什么?工作原理是什么?如何优化多模块都使用AIDL的情况?
答:AIDL是android提供的接口定义语言,Android Interface Definition Language。简化Binder的使用,轻松地实现IPC进程间通信机制,AIDL生成一个对象的代理类,通过它客户端可以实现间接调用服务端对象的方法。
如果优化多模块都使用AIDL:
每个业务模块创建自己的AIDL接口并创建Stub的实现类,向服务端提供自己的唯一标识和实现类。服务端只需要一个Service,创建Binder连接池接口,根据业务模块的特征来返回相应的Binder对象。客户端调用时通过Binder连接池,即将每个业务模块的Binder请求统一转发到一个远程Service中执行,从而避免重复创建Service。
工作原理:
客户端AIDLActivity和服务器端AIDLService是同过BookManager这个aidl接口文件来实现通信的,从用户角度看,是AIDLService和AIDLActivity在进行通信,实际上是客户端的本地代理Proxy在和服务器端的Stub类通过transact和onTransact进行通信;
梳理一下Stud-Proxy的工作流程:
(1)AIDLService中的IBinder对象mBookManager是Stub的具体实现,在AIDLService和AIDLActivity绑定的时候被返回;
(2)被返回的mBookManager最终作为客户端onServiceConnected中的参数;
(3)客户端AIDLActivity会通过本地代理Proxy调用Stub中的静态方法asInterface,mServiceBinder作为参数,最后拿到接口对象mBookManager;
在asInterface方法中,有如下判断流程:
(1)判断Binder是否处于当前进程,若不在,则构建Proxy并返回,构建Proxy时,把mBookManager赋值给mRemote;
(2)Proxy在实现的接口getInformation会调用mRemote的transact方法,而Binder的通信是靠transact和onTransact实现的;
(3)最后会走到Stub的onTransact,完成对mServiceBinder的调用;
25,dispatchTouchEvent return false,return true,return super.dispatchTouchEvent
onInterceptTouchEvent return false, retur true, return super.onInterceptTouchEvent
onTouchEvent return false ,return true,return super.onTouchEvent
描述一下以上三个方法的三种不同return的含义?
答: dispatchTouchEvent 的三个返回值代表含义
- true 表示这个事件被当前的View消费,会传递给当前View的onInterceptTouchEvent方法处理。
- false 表示这个事件不会再往上(内)层的View传递,而是直接交给下(外)层View的onTouchEvent方法去处理
- super.ondispatchToucEvent() 表示会将此事件传递给上(内)层View的dispatchOnTouchEvent方法去处理。
答:onInterceptTouchEvent的三个返回值代表含义
(注:View没有onInterceptTouchEvent方法,ViewGroup才有) - true 按下去的drown事件被onInterceptTouchEvent处理完后返回true,之后的move,up等方法就不会交由onInterceptTouchEvent处理,而是全部(包括drown事件)全部交给改层的onTouchEvent去处理。这样,目标View接收不到任何事件。
- false 按下去的down事件被onInterceptTouchEvent处理完之后返回false,之后的move,up等方法会继续交由onInterceptTouchEvent处理,然后全部(包括down事件)往下传递,直到交由目标View的onTouchEvent去处理。
- super.onInterceptTouchEvent 和返回false是一样的。
答:onTouchEvent()的三个返回值: - false 如果最终需要处理事件的View的onTouchEvent()返回的是false,那么该事件将被传递至上一层的view的onTouchEvent处理。
- true 如果最终需要处理事件的View的onTouchEvent()返回的是true,那么后续事件将可以继续传递给该View的onTouchEvent()处理。
- super.onTouchEvent()与返回true一样。