标签:【每日一题】
一、Activity
1. 什么是Activity? 【2018.1.12更新】
Activity是Android四大组件之一,对应着应用的一个个界面。
Activity实现了Window.Callback和KeyEvent.Callback两个接口,所以用户通过屏幕点击或点击按键可以和Activity交互,以执行各种操作
需要知道的:
1. 创建Activity
就是继承Activity,创建它的子类,并需要再清单文件中声明
2. Activity最常用的2个生命周期方法
是onCreate()和onPause(),onCreate()是必须实现的,用来初始化Activity,通过setContentView()来使用布局资源定义UI;onPause()用来在用户离开时保存或提交数据
3. Activity通过Intent进行通信,有2种启动方式
第一种解释:不带返回值、带返回值
startActivity()
startActivityForResult()+onActivityResult(),目标Activity通过setResult()返回值
第二种解释:显示启动、隠式启动
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
4. Activity有4种启动模式
可在清单文件中指定,也可在代码中通过Intent标志指定
Intent intent = new Intent(this,LogInActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
standard:
默认启动模式,每次创建新实例,放于栈顶
singleTop:
单一顶部,目标Activity在返回栈最上方,则只调用它的onNewIntent()方法,不创建实例;如果不在最上方,重新创建实例
singleTask:
单一任务栈,在指定的返回栈中只能有一个实例;返回栈中不存在,创建实例;已存在,调用onNewIntent(),并清除其上面所有Activity;如果A启动B,B位于其他返回栈,会将B所在的返回栈移动到A所在的任务栈顶部
singleInstance:
单一实例:创建单独新的返回栈,创建实例,放入其中
6. Activity有4种状态
运行
onCreate() > onStart() > onResume() 阶段
onStop() > onRestart() > onStart() > onResume() 阶段
暂停
onResume() > onPause() 阶段
停止
onPause() > onStop() 阶段
死亡
onStop() > onDestory() 阶段
7. Activity有7个生命周期,对应7个生命周期方法
onCreate()
首次创建Activity时调用,可以做一些初始化工作。始终后接 onStart()
onStart()
正在启动Activity,在 Activity 即将对用户可见之前调用。如果 Activity 转入前台,则后接 onResume(),如果 Activity转入隐藏状态,则后接 onStop()
onResume()
Activity已经启动,在 Activity即将开始与用户进行交互之前调用。始终后接 onPause()
onPause()
正在停止,当系统即将开始继续另一个 Activity 时调用。不能做耗时操作,因为必须先执行完旧Activity的onPause(),才能执行新Activity的onResume()。如果 Activity 返回前台,则后接 onResume(),如果 Activity 转入对用户不可见状态,则后接 onStop()
onStop()
即将停止,在 Activity 对用户不再可见时调用。可以做一些重量级的回收操作,同样不能太耗时。如果 Activity 恢复与用户的交互,则后接 onRestart(),如果 Activity 被销毁,则后接 onDestroy()。
onDestory()
即将销毁,在 Activity 被销毁前调用。做一些最终的资源释放
onRestart()
正在重新启动Activity,在 Activity 已停止并即将再次启动前调用。始终后接 onStart()
onStart()和onStop()是从Activity是否可见的角度来回调的
onResume()和onPause()是从Activity是否位于前台的角度回调的
8. Activity有两个重要的处理配置变更,保存Activity状态的方法
onSaveInstanceState() 保存状态
在Activity异常终止的情况下,才会被调用,如旋转屏幕配置发生变更,这个方法调用在onStop()之前
onRestoreInstanceState()
异常终止后被重新创建会被调用,调用在onStart()之前
系统会自动帮我们做一些回复工作,如Activity的视图结构,其中的文本框输入内容等
2. Activity横竖屏切换时的生命周期
测试环境:Android 5.0
1. 未设置android:configChanges
横竖屏切换都是,销毁,重建;onPause > onStop > onDestory > onCreate > onStart > onResume
2. 设置android:configChanges="orientation"
同上,销毁,重建
3. 设置android:configChanges="orientation|keyboardHidden"
同上,销毁,重建
4. 设置android:configChanges="orientation|keyboardHidden|screenSize"
或
android:configChanges="orientation|screenSize"
只回调onConfigurationChanged()方法
其实,只是想监测到横竖屏的变化只要使用orientation + screenSize两个属性就行了,keyboardHidden是监测软键盘变化的
另一个说是切换成竖屏调用两次生命周期的,这个网上有说是2.2版本是这样
二、 Service 【2018.1.16更新】
1. 什么是Service?
Service是四大组件之一,它表示应用程序希望执行长时间运行的操作,而不与用户交互,或为其他应用程序提供功能。
需要知道的
1. 创建服务
创建服务就是创建Service的子类,需要在清单文件中声明
2. 服务分为2种形式,2种启动方式,2种生命周期
1.启动
通过startService()启动,一旦启动,服务即可在后台无限期运行,即使启动服务的组件已被销毁也不受影响,任务完成后自行停止
2.绑定
通过调用bindService() 绑定启动,绑定服务的生命周期会跟调用者关联起来,调用者退出,服务也会跟着销毁
3. Service可以通过startForeground()请求运行在前台
此方法采用两个参数:唯一标识通知的整型数和状态栏的 Notification。例如:
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
2. 是使用Service还是使用线程?
简单地说,服务是一种即使用户未与应用交互也可在后台运行的组件。 因此,您应仅在必要时才创建服务。
如需在主线程外部执行工作,不过只是在用户正在与应用交互时才有此需要,则应创建新线程而非服务。 例如,如果您只是想在 Activity 运行的同时播放一些音乐,则可在 onCreate() 中创建线程,在 onStart() 中启动线程,然后在 onStop() 中停止线程。您还可以考虑使用 AsyncTask 或 HandlerThread,而非传统的 Thread 类。
请记住,如果您确实要使用服务,则默认情况下,它仍会在应用的主线程中运行,因此,如果服务执行的是密集型或阻止性操作,则您仍应在服务内创建新线程。
3. Service运行在哪个线程?是否可以做耗时操作?
默认情况,Service运行在主线程,所以不能做耗时操作。可以通过清单文件中配置android:process属性指定service所在的进程
4. Service中是否可以吐司?
可以的,Service是Context的子类,正好可以用作Toast的第一个参数
5. Activity与Service通信方式?【2018.1.17更新】
1. Binder
2. Messenger
3. BroadcastReceiver
4. EventBus
5. AIDL
6. 什么是IntentService?
IntentService是一种特殊的Service,它继承了Service并是一个抽象类,它使用工作线程逐一处理所有启动请求。如果您不要求服务同时处理多个请求,这是最好的选择。 您只需实现 onHandleIntent() 方法即可,该方法会接收每个启动请求的 Intent,使您能够执行后台工作。
IntentService 执行以下操作:
* 创建默认的工作线程,用于在应用的主线程外执行传递给 onStartCommand() 的所有 Intent。
* 创建工作队列,用于将 Intent 逐一传递给 onHandleIntent() 实现,这样您就永远不必担心多线程问题。
* 在处理完所有启动请求后停止服务,因此您永远不必调用 stopSelf()。
* 提供 onBind() 的默认实现(返回 null)。
*提供 onStartCommand() 的默认实现,可将 Intent 依次发送到工作队列和 onHandleIntent() 实现。
综上所述,您只需实现 onHandleIntent() 来完成客户端提供的工作即可。(不过,您还需要为服务提供小型构造函数。)
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
}
}
三、BroadcastReceiver 【2018.1.18更新】
1. 什么是BroadcastReceiver?
BroadCastReceiver 是 Android 四大组件之一,主要用于接收系统或者 app 发送的广播事件
需要知道的
1. 广播有2种注册方式
BroadcastReceiver是Android四大组件中唯一一个可以不在清单文件中注册的组件
1.清单文件注册(静态注册)
//用于接收网络状态改变时发出的广播
只要应用程序被部署到手机上,就立刻生效,不管进程是否处于运行状态;
2.代码注册(动态注册)
// 选择在Activity生命周期方法中的onCreate()中注册
@Override
protected void onCreate(){
super.onCreate();
// 1. 实例化BroadcastReceiver子类 & IntentFilter
mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
// 2. 设置接收广播的类型
intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);
// 3. 动态注册:调用Context的registerReceiver()方法
registerReceiver(mBroadcastReceiver, intentFilter);
}
// 注册广播后,要在相应位置记得销毁广播
// 即在onDestory() 中unregisterReceiver(mBroadcastReceiver)
// 当此Activity实例化时,会动态将MyBroadcastReceiver注册到系统中
// 当此Activity销毁时,动态注册的MyBroadcastReceiver将不再接收到相应的广播。
@Override
protected void onDestory() {
super.onDestory();
//销毁在onCreate()方法中注册的广播
unregisterReceiver(mBroadcastReceiver);
}
}
代码运行了,广播接收者才生效,如果代码运行结束,广播接收者,就失效;对于动态广播,有注册就必然得有注销,否则会导致内存泄露,重复注册、重复注销也不允许
2. 广播分为2种类型
1. 有序广播 sendOrderedBroadcast();
按照被接收者的优先级顺序,在被接收者中依次传播。比如有三个广播接收者 A,B,C,优先级是 A >B > C。那这个消息先传给 A,再传给 B,最后传给 C。每个接收者有权终止广播,比如 B 终止广播,C 就无法接收到。此外 A接收到广播后可以对结果对象进行操作,当广播传给 B 时,B 可以从结果对象中取得 A 存入的数据
2. 普通广播 sendBroadcast();
完全异步,逻辑上可以被任何广播接收者接收到。优点是效率较高。缺点是一个接收者不能将处理结果传递给下一个接收者,并无法终止广播 intent 的传播。
3. 广播的生命周期
a.广播接收者的生命周期非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁;
b. 广播接收者中不要做一些耗时的工作,超出10秒会弹出 Application No Response 错误对话框;
c. 最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉;
d. 耗时的较长的工作最好放在服务中完成;
2. 广播的优先级设定?优先级对无序广播有效吗?
1. 优先级别声明在中,取值为[-1000,1000]数值越大优先级别越高。可通过代码中filter.setPriority(10)方式设置,也可在清单文件中设置
2. 有效
3. 动态注册的广播谁的优先级高?
谁先注册谁的优先级高
4. 如何判断接收到的是有序还是无序广播?
isOrderedBroadcast();该方法是BroadcastReceiver 类中提供的方法,用于告诉我们当前的接收到的广播是否为有序广播
5. Android中如何做到自定义的广播只能有指定的app接收 ?
自定义权限,给自己的receiver加上此权限,发送广播时加上权限
四、ContentProvider 【2018.1.19更新】
1. 什么是ContentProvider?
ContentProvider是Android四大组件之一,管理对中央数据存储区的访问。它封装数据,为存储和访问数据提供统一的接口,并提供用于定义数据安全性的机制。 主要作用是向其他应用提供数据,并保护数据访问的安全性。
需要知道的
1. 创建ContentProvider
创建ContentProvider就是创建它的子类,并需在清单文件中注册
2. ContentResolver
内容解析者,通过URI访问ContentProvider,获取数据
3. 原理
Android底层的Binder机制
2. 为什么要用 ContentProvider?它和 sql 的实现上有什么差别?
ContentProvider屏蔽了数据存储的细节,内部实现对用户完全透明,用户只需要关心操作数据的 uri 就可以了, ContentProvider 可以实现不同 app 之间共享。
Sql 也有增删改查的方法,但是 sql只能查询本应用下的数据库。而 ContentProvider 还可以去增删改查本地文件. xml 文件的读取等
3. 说说 ContentProvider、ContentResolver、ContentObserver 之间的关系
ContentProvider 内容提供者,用于对外提供数据
ContentResolver.notifyChange(uri)发出消息
ContentResolver 内容解析者,用于获取内容提供者提供的数据
ContentObserver 内容监听器,可以监听数据的改变状态
ContentResolver.registerContentObserver()监听消息。
这个系列就结束了,感觉我的这个面试题有点跑偏了,有些知识总结的感觉了,具体的Android四大组件,后面我准备单独拿出了复习、练习,整理出博客。
后面的面试题系列,我大概思路是:直接网上搜罗,每天更新,只有答案,没有详解,如果复杂的不理解的,我会单独学习,整理博客。可能不止每天一题,能吸收的就多两题,主要是督促自己每天能够看点面试题