主要有这么几个问题
1.kotlin foreach如何跳出当前循环
答:在foreach前面打标签。使用return@标签的方式。
2.广播的两种注册方式的区别?
答:广播主要有两种方式去注册。一种是静态广播,一种是动态广播。
静态方式是指在mainfest.xml里去注册,然后在安装的时候,是由PackageManagerService去注册。
动态的话则是使用registerReceiver的方式来注册。
动态广播的优先级>静态广播,也就是说动态广播接收的更快。 动态广播的生命周期和它的context有关。静态广播则是常驻的。应用退出后仍然可以接收到。
一些特殊的广播,必须使用动态广播,静态不起效果。比如锁屏。
3.自定义viewGroup,使子view可以垂直排列,类似linearlayout。
答:这里注意两个方法就可以。
1.第一个方法是onMeasure()方法,这个方法是测绘自己的宽高。 在这个方法里,便利自己的子view,比较出最大宽度再加上paddingleft和paddingright,作为自己的宽度。然后把子view的高度相加,然后再加上paddingtop和paddingbottom作为自己的高度。最后调用setMeasureDimension(W,H)作为自己的宽高。代码如下:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//先定义自己的宽高初始值
int measureWidth = 0;
int measureHeight = 0;
int count = getChildCount();
for(int i=0; i < count; ++i) {
View v = getChildViewAt(i);
if(v.visibility() != View.Gone) {
//获取子view的宽高
measureChild(v,widthMesaureSpec,widthMesureSpec);
//取出最大宽度作为viewGroup的宽度
mesasureWidth = Math.max(messasureWdith,v.getMesuareWidth);
//把高度相加作为自己的高度
measureHeight += v.getMeasureHeight();
}
}
//加上padding
mesuredWidth += getPaddingLef()+ getPaddingRight();
mesauredHeight += getPaddingTop() + getPaddingBottom();
//度量自己,调用setMeasureDimension()
setMeasureDimension(measureWidth,measureHeight);
}
2.第二个,就是onLayout()方法。这个方法的作用就是布局自己的子view.也就是说画一些框框,放置自己的子view.
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//获取子view的数量
int count = getChildCount();
for(int i=0; i< count;++i) {
View v = getChildAt(i);
if (v.getVisibility() != View.Gone)
{
int childWidth = v.getMeasureWidth();
int childHeight = v.getMeasuredHeight();
//开始摆放
v.layout(l,t,l+childWidht,t+childHeight);
//注意,这里主要是改变他的top值
t += childHeight;
}
}
}
4.使用handler的时候,是怎么把Message放到messageQueue里面去的?
答:先说Handler的流程。 Handler.sendMessageAtTime()。在这个方法里会调用enqueueMessage(queue, msg, uptimeMillis)这个方法,这个方法里,会调用messageQueue的enqueueMessage(msg,time)方法,把Meessage放到mssageQueue队列里的。
到这里Handler就把消息发出去了。
接下来就是取消息。Looper从队列里取消息,就是调用Handler的dispatchMessage方法。
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
大家从这个代码块里可以看出,当Message携带的操作是以Runnable形式存在的,就会用handleCallback,然后调用run方法。否则就会调用handlerMessag。我们通常都是继承handler重写这个方法,用来处理消息。
5.常见的内存泄漏,以及解决方案。
1.android特色的在activity中使用handler内部类。handler持有activity,handler又被Message持有,message又被messageQueue持有。当这个message还没有到执行时间的时候,activity进行销毁,却发现被持有销毁不了。解决:静态内部类的方式。或者使用虚引用。
2.匿名内部类。内部类默认持有外部类的对象。如果内部类执行了耗时操作,就会泄漏。
3.资源释放。比如数据库的打开和关闭,文件流的打开和关闭,还有bitmap等。我们要根据生命周期,去手动关闭。
4.注册了一些东西,在ondestroy的时候,要看看注册的时候干了什么,到关闭的时候有没有相应的资源需要关闭。
6.两个Activity,从A启动到B的生命周期?
答:onPauseA() -> onCreateB() -> onStartB() -> onResumeB() -> onStopA()
此时,如果再从B返回到A呢?
onPauseB() -> onReStartA() -> onstartA() -> onResumeA() -> onStopB() -> onDestroyB()