面试_android基础
1.四大组件
1.1 activity和fragment的通信方式
- handler:Activity声明一个handler,fragment保存这个handler实例;
- 广播:在 Activity 中注册广播接收器,在 Fragment中发送广播。
- 接口回调:fragment定义接口,调用接口中的抽象方法,activity实现这个接口,通过抽象方法参数传递数据。
- eventbus:Activity注册订阅者,fragment发送消息
- Bundle setArguements()/getArguements()
DiscoverFragment discoverFragment = new DiscoverFragment();
Bundle bundle = new Bundle();
bundle.putString("email", email);
discoverFragment.setArguments(bundle);
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_discover, null);
Bundle bundle = getArguments();
//这里就拿到了之前传递的参数
email = bundle.getString("email");
return view;
}
1.2 Activity LauncherMode
- standard:默认启动模式,返回栈中会创建多个activity实例;
- singletop:创建活动时会先读取返回栈栈顶活动,如果与栈顶活动相同会直接引用,如果不同则创建新activity实例。
- singleTask:创建活动时会先查询返回栈中是否存在该activity,如果存在则直接引用该activity,并把该activity上的所有活动都出栈。主页
- singleInstance:活动会启用一个新的返回栈来管理这个活动。
1.3 BroadcastReceiver和LocalBroadcastReceiver
- BroadcastReceiver:跨应用广播,利用Binder机制实现,支持动态和静态两种方式注册方式。
- LocalBroadcastReceiver:应用内广播,利用Handler实现,利用了IntentFilter的match功能,提供消息的发布与接收功能,实现应用内通信,效率和安全性比较高,仅支持动态注册。
1.4 Context
定义:应用的运行时环境/应用的上下文
结构:service、activity和application都是context的子类
内存泄漏问题:单例构造器中以context作为参数,activity调用单例传入this,如果acitivity生命周期已经结束,而单例的生命周期没有结束,就会造成activity的内存泄漏。
1.5 IntentFilter是什么?有哪些使用场景
IntentFilter:意图解释器,可以给四大组件配置自己关心的action。例如启动某个activity时
1.6 Service的startService和bindService的生命周期
startService:onCreate-onStartCommand-onDestroy
bindService:onCreate-onBind-onUnBind-onDestroy
onCreate方法在整个生命周期内只会被调用一次,即只存在一个Service实例
如果对一个Service既start了又bind了,则需要调用unBind和stopService方法,onDestroy才会执行。
场景:
- startService开启后只要不调用stopService就会一直存在,需要长时间在后台运行的服务使用startService;
- bindService开启后除了调用unBindService,所绑定的activity组件关闭后服务也会关闭,跟随组件生命周期的场景使用bindService。
1.7 activity的启动流程
- Launcher进程通过Binder IPC向system_server进程的AMS发送startAcitivity请求;
- system_server进程收到请求后通过socket向Zygote进程发送创建进程的请求;
- Zygote进程fork出新的子进程,即Application进程;
- App进程通过反射创建ActivityThread主线程并对其进行初始化,然后通过Binder IPC向system_server进程的AMS发起attach application请求;
- system_server进程的AMS收到attach application请求后通知 ApplicationThread bindApplication,然后发送 H.BIND_APPLICATION 消息;
- 主线程收到绑定成功后,初始化Application;
- system_server 进程的 AMS 在 bindApplication 后通过 Binder IPC 向 App 进程发送 scheduleLaunchActivity 请求;
- App进程的 ApplicationThread在收到请求后,通过 handler 向主线程发送 LAUNCH_ACTIVITY 消息
1.7 服务保活
1.设置为前台服务
2.利用系统广播拉活、利用系统服务拉活
1.8 说下Activity在切换横竖屏时,aictivity的生命周期变换
如果没有配置activity的configChanges属性,则:
竖屏启动:onCreate-onStart-onResume
切换横屏时:onPause-onSaveInstanceState-onStop-onDestroy-onCreate-onStart-onRestoreInstanceState-onResume
如果配置了configChanges属性
:android:configChanges="orientation|keyboardHidden|screenSize"则只会调用onConfigurationChanged方法。
2.多线程
2.1 HandlerThread
工作在子线程的Handler
- 创建
HandlerThread实例对象HandlerThread mHandlerThread = new HandlerThread("mHandlerThread");
- 启动线程
mHandlerThread .start();
- 创建Handler对象,重写handleMessage方法
Handler mHandler= new Handler( mHandlerThread.getLooper() ) { @Override public boolean handleMessage(Message msg) { //消息处理 return true; } });
- 使用工作线程Handler向工作线程的消息队列发送消息:
Message message = Message.obtain(); message.what = “2” message.obj = "骚风" mHandler.sendMessage(message);
- 结束线程,即停止线程的消息循环
mHandlerThread.quit();
2.2 IntentService
IntentService:是Service的子类,自动创建了一个工作线程,使用工作线程逐一处理所有的启动请求,在任务执行完毕后会自动停止服务。
onHandlerIntent方法会接收每个启动请求的Intent,能够执行后台工作和耗时操作。
public class MyIntentService extends IntentService {
public static final String TAG ="MyIntentService";
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
boolean isMainThread = Thread.currentThread() == Looper.getMainLooper().getThread();
Log.i(TAG,"is main thread:"+isMainThread); // 这里会打印false,说明不是主线程
// 模拟耗时操作
download();
}
/**
* 模拟执行下载
*/
private void download(){
try {
Thread.sleep(5000);
Log.i(TAG,"下载完成...");
}catch (Exception e){
e.printStackTrace();
}
}
}
2.3 AsyncTask的优缺点
优点:使用简单方便
缺点:默认任务串行执行,效率低。
复习AsyncTask的用法
2.4 Activity的runOnUiThread
会判断当前线程是否是主线程,如果是主线程则直接run,如果不是主线程则通过handler的post方法切换到主线程
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
2.5子线程能否更新UI
可以更新UI但是不建议这么做,会造成应用crash。因为在执行UI更新操作时会检查Thread,判断当前线程不是主线程则会抛异常。