Android面试知识点汇总(一)
程序员文章站
2022-04-11 18:15:56
...
Android基础
一、Activity相关
1.Activity生命周期
- Activity是与用户交互的接口
- Android系统通过Activity栈的形式来管理Activity
- Active/Paused/Stopped/Killed
正常情况下回调方法:
- onStart()回调表示可见但无法与用户交互。
- onResume()回调表示处于前台,可见且可与用户交互。
- onPause()表示正在停止,与onResume()成对出现。
- onStop()在onPause()执行完以后立即执行,表示即将停止或完全由一个新的Activity覆盖,此时Activity不可见,只能在后台运行。
- onCreate()与onDestroy()成对出现,前者进行初始化,后者做回收、资源释放工作。
- onRestart()是当Activity由onStop()变为onStart()方法之间回调。
异常情况下(系统配置发生改变或内存不足等情况下,Activity异常终止时)系统回调方法:
- onSaveInstanceState(Bundle outState)保存当前Activity状态信息,用此方法恢复数据是需进行Bundle非空判断。
- onRestoreInstanceState(Bundle savedInstanceState),当Activity被重新创建后调用,Bundle为非空,不需进行非空判断。
总结
- Activity正常启动:onCreate-onStart-onResume
- 点击back回退:onPause-onStop-onDestroy
- 打开新的Activity:onPause-onStop
- Activity异常:onSaveInstanceState保存数据
- Activity重新创建:调用onRestoreInstanceState
2.Activity通信
Activity之间通信的三种方式:Intent/Bundle、类静态变量、全局变量
Activity与Fragment通信:Bundle、直接在Activity中定义方法
利用Bundle,Activity将数据传到依附它的Fragment上:
public class FragmentActivity1 extends Activity {
public String productId;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = new Bundle();
bundle.putString(Constant.NTENT_D,productId);
Fragment fragment = null;
fragment.setArguments(bundle);
}
}
public class Fragment1 extends Fragment {
public String productId;
@Override
public void onStart() {
super.onStart();
if (isAdded()){//判断Fragment是否已经依附Activity
productId = getArguments().getString(Constant.NTENT_D);
}
}
}
通过定义方法通信:
public class FragmentActivity2 extends Activity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public String getTitles(){
return "getTitle";
}
}
public class Fragment2 extends Fragment {
public String titles;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
titles = ((FragmentActivity2) activity).getTitle();
}
}
Fragment与Activity通信:接口回调
- 在fragment中定义一个内部回调接口,使包含此fragment的Activity实现这个接口,则fragment可调用此接口传递数据
- 当fragment添加到Activity中时调用fragment生命周期方法中的onAttach()方法,可在此方法中检查相应Activity是否实现了fragment中定义的内部接口。即对它类型转换,赋值给fragment中对应的内部接口
- 调用onDetach时,要将传递进来的activity对象释放掉
public class Fragment3 extends Fragment implements View.OnClickListener{
// 定义用来与外部activity交互,获取到宿主activity
private FragmentListener listener;
// 定义了所有activity必须实现的接口方法
public interface FragmentListener {
void process(String str);
}
// 当Fragment被加载到activity的时候会被回调
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof FragmentListener) {
listener = (FragmentListener)activity;
} else {
throw new IllegalArgumentException("activity must implement fragment interface");
}
}
@Override
public void onClick(View v) {
listener.process("我是接口");
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
}
二、事件分发机制
核心方法
- dispatchTouchEvent()
- onInterceptTouchEvent()
- onTouchEvent()
1.Activity事件分发
2.ViewGroup事件分发
3.View事件分发
三、异步消息处理机制相关面试问题
1.Handler
首先在主线程中为主线程创建Looper(Looper为线程持有),同时在Looper内部创建一个消息队列(MessageQueue对象)。当创建Handler时会取出当前线程的Looper,通过这个Looper不断轮询消息队列中的Message。Handler在子线程中发送消息的实质就是在MessageQueue中添加一条Message,最后通过Looper中的消息循环取得Message再交给Handler进行处理。
分析源码可知:
- 创建Handler对象时如果Looper为空则会抛出异常。因为Handler发送消息必须发送到指定的消息队列中,而消息队列由Looper管理,所以创建Handler对象必须在当前线程中有指定Looper对象。
- 消息队列核心方法为插入队列enqueueMessage()和读取和删除next(),内部由单链表实现。
- 为确保每一个线程获取到的Looper都是唯一的,Looper.prepare()方法内部用sThreadLocal容器来保存Looper对象本身。ThreadLocal也称为线程本地变量,它为每个变量在每个线程都创建一个数据副本。
2.AsyncTask
Handler+线程池。使用线程池的主要原因是避免不必要的创建和销毁线程的开销。
分析源码可知:
- 手机CPU核数(CPU_COUNT)+1作为AsyncTask线程使用的线程数核心(CORE_POOL_SIZE)大小,CPU核数*2+1作为线程池最线程数(MAXIMUM_POOL_SIZE)大小,线程池为静态。
- 创建了ThreadFactory实例用于创建线程池,其中mCount变量为原子类型,为保证后面获得此数据时线程安全。
- AsyncTask内部串行执行任务。
- (未完待续)