安卓基础学习笔记(六)

/ 0评 / 0

Java线程
-----------------------------------
进程的特点:可以同时存在多个进程,这些进程会交替执行,且切换频率高,每次切换到某个进程时,该进程运行的时间比较随机。
进程是若干个线程的集合,当进程运行时,真正运行的是进程中的线程。
每个正在执行的进程中,都至少存在1个正在执行的线程。
每个进程中,可以存在若干个线程。
线程具有以上提到的进程的所有特征。
线程可以理解是轻量级的进程。
每个进程启动时,会默认开启1个线程,该线程通常称之为“主线程”。
开发者可以在程序中自由的创建新的线程,并启动,这些新的线程通常称之为“子线程”,或者“工作线程”。

创建并启动线程
-----------------------------------
【方式1】
1. 自定义类,继承自java.lang.Thread类
2. 在自定义类中重写public void run()方法
3. 当需要启动线程时,创建自定义类的对象,并调用该对象的start()方法
【方式2】
1. 自定义类,实现java.lang.Runnable接口
2. 在自定义类中重写public void run()方法
3. 当需要启动线程时,创建自定义类的对象,然后,创建Thread类的对象,在创建Thread类对象时,将自定义类对象作为构造方法的参数,最后,调用Thread类对象的start()方法

ANR
--------------------------
ANR:Application Not Responding:应用程序无响应
ANR是由于主线程执行任务消耗时间过长导致的。

Android中的UI线程模型
--------------------------
UI:User Interface
在Android系统中,主线程是用于初始化界面、响应用户在界面上的操作等等的,所以,主线程也叫做UI线程。
UI线程执行时间过长,则可能导致ANR!如果是在Activity中,则超过5s就可能出现ANR,如果是在BroadcastReceiver中,则超过10s就可能出现ANR。
对于开发者而言,只要是消耗时间可能比较长的操作,都应该规避处理。
解决ANR问题的根本方法:把耗时操作放在子线程中运行!

关于在子线程中更新UI
--------------------------
小结:不允许在子线程中直接更新UI,否则应用程序将崩溃
官方解释:只能创建UI控件的线程,才可以操作这些UI控件,而创建UI控件的过程都是由主线程/UI线程完成的
源码解释:只有拥有ViewRoot的线程才可以操作UI控件,主线程默认即有ViewRoot,而线程通常没有ViewRoot。
解决方案:当需要在子线程中更新UI时,调用runOnUiThread()方法即可。

ProgressBar:进度条
--------------------------
【属性】
1. style -> 进度条的样式
2. android:max -> 进度的最大值
3. android:progress -> 当前进度

【方法】
void setMax(int)
int getMax()
void setProgress(int)
int getProgress()

SeekBar:可拖拽的进度条
--------------------------
SeekBar是ProgressBar的子类,使用方法可以完全参考ProgressBar的使用方法。

进程的优先级
---------------------------------
在Android系统中,当内存资源不足时,系统会自动清理一部分已经打开的应用程序占用的内存空间,以保证有足够的内存来运行用户当前需要运行的程序。在自动清理的过程中,会根据各进程的优先级,优先清理优先级较低的进程。
进程的优先级从高到低分别是:
1. 前台进程:进程中存在可见并可控的Activity
2. 可见进程:进程中存在局部可见(可见却不可控的)的Activity
3. 服务进程:存在正在执行的Service的进程
4. 后台进程:进程中所有的Activity都被置于后台
5. 空进程:被销毁的进程

Service:服务
---------------------------------
Service是Android系统的核心组件之一,是由系统进行管理和维护的。
【定位】
Service是没有界面的;
Service适合在后台执行长时间的任务;
Service是单例的;
注意:Service是运行在主线程的,所以,如果需要让Service执行耗时操作,需要在Service中开启子线程来完成
【创建步骤】
1. 继承:自定义类继承自android.app.Service类
2. 注册:在AndroidManifest.xml的节点下,添加节点,并配置该节点的android:name属性完成注册

启动模式的Service
---------------------------------
【启动Service】
调用startService(Intent)方法即可启动Service
【停止Service】
1. 调用stopService(Intent)方法即可停止Service
2. 在Service内部调用stopSelf()方法可停止Service
【Service的生命周期】
onCreate() -> 当创建时,该方法仅当第1次启动时被调用
onStartCommand() -> 当开始执行某个指令时,该方法在每次启动时都会被调用
onDestroy() -> 当销毁时,该方法在Service被停止后执行
【Service的粘性】
Service的粘性表现为:当Service被意外终止时,会自动重启。
Service是否粘性,是根据onStartCommand()方法的返回值决定的,取值为Service类的常量:
START_STICKY -> 粘性的
START_STICKY_COMPATIBILITY -> 兼容模式的粘性的
START_NOT_STICKY -> 非粘性的
START_REDELIVER_INTENT -> 粘性的,且重新传递Intent

绑定模式的Service
---------------------------------
绑定模式的Service是实现其它组件,例如Activity,与Service实现绑定关系,当实现了绑定关系后,Activity可以和Service实现组件之间的通信。
【绑定流程】
1. 创建WorkService类,继承自Service
2. 注册Service
3. [Activity] 声明内部类InnerServiceConnection,实现ServiceConnection接口
4. [Activity] 调用bindService()方法实现绑定,其中,方法的第1个参数是Intent对象,用于指定被激活的组件,第2个参数以上第3个步骤的内部类对象,且应该被声明为全局变量,第3个参数取值为常量BIND_AUTO_CREATE
5. [IMusicPlayer] 声明新的接口

文件IMusicPlayer,并在接口中声明那些由Service实现、由Activity调用的方法,例如void play()等等
6. [Service] 声明内部类InnerBinder,继承自Binder,实现IMusicPlayer接口
7. [Service] 在onBind()中,创建InnerBinder的对象,作为该方法的返回值
8. [Activity] 声明IMusicPlayer的全局变量player,该变量的值将在InnerServiceConnection的onServiceConnected()方法中,根据第2个参数强制类型转换得到。
9. [Activity] 在需要的时候,通过player执行各种已经在接口中声明的方法,而这些方法最终都会是Service在运行的
【绑定的Service的生命周期】
onCreate() -> 当创建时,第1次绑定时被调用
onBind() -> 当绑定时,第1次绑定时被调用
onDestroy() -> 当销毁时,解除绑定时被调用
【解除绑定】
可以通过unbindService(ServiceConnection)解除绑定。
注意:如果Activity绑定了Service,在没有解除绑定之前,直接退出Activity会导致错误(该错误不会显示在手机上)。

评论已关闭。