Android 基础篇
1. Activity详细解析
-
Android中的activity全都归属于task管理 。task 是多个 activity 的集合,这些 activity
按照启动顺序排队存入一个栈(即“back stack”)。android默认会为每个App维持一个task来存放该app的所有activity,task的默认name为该app的packagename。 -
首先打开一个新的activity实例的时候,系统会依次调用 onCreate() -> onStart() -> onResume()
然后开始running; running的时候被覆盖了(从它打开了新的activity或是被锁屏,但是它依然在前台运行, lost focus but is still visible),系统调用onPause();
该方法执行activity暂停,通常用于提交未保存的更改到持久化数据,停止动画和其他的东西。但这个activity还是完全活着(它保持所有的状态和成员信息,并保持连接到窗口管理器);
如果用户返回到onStop()状态的activity(又显示在前台了),系统会调用 onRestart() -> onStart()
-> onResume() 然后重新running 在activity结束(调用finish ())或是被系统杀死之前会调用onDestroy()方法释放所有占用的资源 -
activity生命周期中三个嵌套的循环:
activity的完整生存期会在 onCreate() 调用和 onDestroy()调用之间发生。
activity的可见生存期会在 onStart() 调用和 onStop()调用之间发生。
系统会在activity的整个生存期内多次调用 onStart() 和onStop(),
因为activity可能会在显示和隐藏之间不断地来回切换。
activity的前后台切换会在 onResume() 调用和onPause() 之间发生。
因为这个状态可能会经常发生转换,为了避免切换迟缓引起的用户等待,这两个方法中的代码应该相当地轻量化。
/**
* 可能被回收内存前保存状态和信息,
*
* 在activity 可能被回收之前 调用,用来保存自己的状态和信息,
* 以便回收后重建时恢复数据(在onCreate()或onRestoreInstanceState()中恢复)。
* 旋转屏幕重建activity会调用该方法,但其他情况在onRause()和onStop()状态的activity不一定会调用。
* @param outState
* @param outPersistentState
*
* 系统灵活的来决定调不调用该方法,但是如果要调用就一定发生在onStop方法之前,
* 但并不保证发生在onPause的前面还是后面
*/
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
//可能被回收内存前保存状态和信息,
Bundle data = new Bundle();
data.putString("key", "last words before be kill");
outState.putAll(data);
super.onSaveInstanceState(outState, outPersistentState);
}
/**
* 判断是否有以前的保存状态信息
* @param savedInstanceState
*
* 这个方法在onStart 和 onPostCreate之间调用,在onCreate中也可以状态恢复,但有时候需要所有布局初始化完成后再恢复状态。
* onPostCreate:一般不实现这个方法,当程序的代码开始运行时,它调用系统做最后的初始化工作。
*/
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if(savedInstanceState!=null){ //判断是否有以前的保存状态信息
savedInstanceState.get("Key");
}
super.onRestoreInstanceState(savedInstanceState);
}
- 启动模式
- “standard” (默认模式)
当通过这种模式来启动Activity时, Android总会为目标 Activity创建一个新的实例,并将该Activity添加到当前Task栈中。这种方式不会启动新的Task,只是将新的 Activity添加到原有的Task中。 - “singleTop”
该模式和standard模式基本一致,但有一点不同:当将要被启动的Activity已经位于Task栈顶时,系统不会重新创建目标Activity实例,而是直接复用Task栈顶的Activity。
- “singleTask”
Activity在同一个Task内只有一个实例。如果将要启动的Activity不存在,那么系统将会创建该实例,并将其加入Task栈顶;
如果将要启动的Activity已存在,且存在栈顶,直接复用Task栈顶的Activity。
如果Activity存在但是没有位于栈顶,那么此时系统会把位于该Activity上面的所有其他Activity全部移出Task,从而使得该目标Activity位于栈顶。
- “singleInstance”
无论从哪个Task中启动目标Activity,只会创建一个目标Activity实例且会用一个全新的Task栈来装载该Activity实例(全局单例).
如果将要启动的Activity不存在,那么系统将会先创建一个全新的Task,再创建目标Activity实例并将该Activity实例放入此全新的Task中。
如果将要启动的Activity已存在,那么无论它位于哪个应用程序,哪个Task中;系统都会把该Activity所在的Task转到前台,从而使该Activity显示出来。
- 开发中Activity的一些问题
一般设置Activity为非公开的
<activity
......
android:exported="false" />
注意:非公开的Activity不能设置intent-filter,以免被其他activity唤醒(如果拥有相同的intent-filter)。
不要指定activity的taskAffinity属性
不要设置activity的LaunchMode(保持默认)
注意Activity的intent最好也不要设定为FLAG_ACTIVITY_NEW_TASK
在匿名内部类中使用this时加上activity类名(类名.this,不一定是当前activity)
设置activity全屏
在其 onCreate()方法中加入:
// 设置全屏模式
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 去除标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
通过配置不同的 action 可以改变Activity属性
例如想把Activity设置为打开图片资源类型的:
<activity android:name=".SmsObserverActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
</intent-filter>
</activity>
2. Service详细解析
- 服务的分类
按运行分类
- 前台服务
前台服务是指那些经常会被用户关注的服务,因此内存过低时它不会成为被杀的对象。 前台服务必须提供一个状态栏通知,并会置于“正在进行的”(“Ongoing”)组之下。这意味着只有在服务被终止或从前台移除之后,此通知才能被解除。 例如,用服务来播放音乐的播放器就应该运行在前台,因为用户会清楚地知晓它的运行情况。 状态栏通知可能会标明当前播放的歌曲,并允许用户启动一个activity来与播放器进行交互。
要把你的服务请求为前台运行,可以调用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, notification);
要从前台移除服务,请调用stopForeground()方法,这个方法接受个布尔参数,表示是否同时移除状态栏通知。此方法不会终止服务。不过,如果服务在前台运行时被你终止了,那么通知也会同时被移除。
- 后台服务
IntentService详细解析
IntentService原理解析文章
ContentProvider实例详解
BroadcastReceiver详细解析
Android异步任务机制之AsycTask
Handler,Looper,MessageQueue关系
Android-SQLite的基本使用
Android系统相机与相册的使用
图片缓存原理
Android数据存储的五种方式
Android跟随手指移动的View
RecyclerView的使用
Android获取SHA1
Recyclerview和Listview的异同.md
初识ConstraintLayout
TabLayout记录
用SpannableString打造绚丽多彩的文本显示效果
解析ConstraintLayout的性能优势
Android新特性介绍,ConstraintLayout完全解析
Android新特性介绍,ConstraintLayout完全解析
Android 一个无限循环滚动的卡片式ViewPager