android线程间通信机制2

UI线程:当一个Android程序启动时,系统会为该程序创建一个进程,然后创建一个线程运行在这个进程中,称为主线程(main thread).主线程主要负责将事件分发到对应的界面控件中,包括控件绘制事件。由于主线程是程序和UI控件交互的线程,所以也被称为UI线程。Android框架中这种在单条线程中进行事件分发及UI交互的机制也被称为Android单线程模型
单线程模型的规则:不要在UI线程中进行耗时操作。不要在UI线程外操作界面控件。
界面控件被设计为非线程安全的,没有线程同步机制的,如果在工作线程进行控件操作将会触发错误。
工作线程:为了不阻塞UI线程,耗时操作应在单独的线程中执行,这样的线程统一被称为工作线程,background or worker thread,Android 系统提供了一些工具用于在工作线程中更新UI线程。为了不阻塞主线程的执行,工作线程中不能执行可以导致主线程进入阻塞状态的操作。
Android中更新UI的几种方式
在工作线程中更新UI:使用View的postInvalidate()方法;使用Activity对象的runOnUiThread()方法;使用View对象及其子类对象的post()和postDelayed()方法。
AsyncTask是Android提供的一种轻量级异步任务类。
AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,这些方法不应该由应用程序调用,开发者需要做的就是实现这些方法。

  1. 子类化AsyncTask
    三个参数
    AsyncTask是一个抽象类,使用时需要创建子类去继承它,继承时需要指定以下3个泛型参数
    AsyncTask”<”Params,Progress,Result>
    Progress:后台任务执行时,如果需要在界面上显示当前进度,则使用这里的泛型作为进度返回值的类型。
    Result:当任务执行完毕后,如果需要对结果进行返回,则使用这里的泛型作为结果返回的类型。

  2. 实现AsyncTask中定义的下面一个或几个方法:
    onPreExecute(), 该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。   
    doInBackground(Params…), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。   
    onProgressUpdate(Progress…),在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。   
    onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.   
    为了正确的使用AsyncTask类,以下是几条必须遵守的准则:

    1. Task的实例必须在UI thread中创建
    2. execute方法必须在UI thread中调用
    3. 不要手动的调用onPreExecute(), onPostExecute(Result),
      doInBackground(Params…), onProgressUpdate(Progress…) 这几个方法
    4. 该task只能被执行一次,否则多次调用时将会出现异常
    5. doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第三个为doInBackground返回和onPostExecute传入的参数。

AsyncTask的机制原理
1.AsyncTask的本质是一个静态的由5个核心线程,最大队列数为128的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务都是提交到静态的线程池中执行。
2.线程池中的工作线程执行DoInBackground(mParams)方法执行异步任务。
3.当任务状态改变后,工作线程会向UI线程发消息,AsyncTask内部的InternalHandler响应这些消息,并调用回调函数。

Android中的进程的分类及其优先级 Android 根据进程所托管的组件的不同,将进程分为以下几类,优先级如下:前台进程>可见进程>服务进程>后台进程>空进程。
在Service中运行线程,可以保证线程所在的进程至少具有服务进程级别的优先级。避免在Activity中或BroadcastReceiver中直接开启线程,随着运行它们所在的进程随时可能会变为较低优先级的进程,线程执行的任务的完整得不到保证。
在service中使用线程的两种方式:使用IntentService;在Service的生命周期方法里使用线程相关类开启线程。 IntentService是一个抽象类,在使用它的时候需要实现onHandleIntent(Intent intent)方法,然后在需要使用它的组件中调用startService(Intent intent)方法发送指令调用它。 IntentService是基于消息队列实现,其内部消息传递是通过Handler方式实现。 优点:使用方便,不需要自己管理线程的创建和Service的销毁。缺点:单个的worker thread,多任务时需要排队。

AsyncTask的注意事项
1.生命周期:有时候我们会认为在Activity中创建的AsyncTask内部类会随着Activity的销毁而被销毁结束。其实并不是这样,AsyncTask会一直执行,直到doInBackground方法执行完成。此时,如果执行cancel(boolean)操作,onCancelled(Result result) 方法会被执行。这样AsyncTask占据的内存才会被通知回收。否则,会继续执行onPostExecute(Result result) 方法。如果我们的Activity销毁之前,没有取消 AsyncTask,这有可能让我们的AsyncTask崩溃(crash)。也就是说我们在Activity销毁之前要手动cancel掉AsyncTask。因为此时AsyncTask已经没有存在的意义了。

于是相对于不能中断的任务,为避免任务一直持有activity,我们可以通过使用静态内部类,并且使用WeakReference来包裹我们的activity以达到更新UI的目的。
弱引用:弱引用是通过WeakReference类实现,使gc可以进行回收。

2.内存泄漏:根据上面对AsyncTask生命周期的分析可以发现,如果AsyncTask被声明为Activity的非静态的内部类,那么AsyncTask会保留一个对创建了AsyncTask的Activity的引用。如果Activity已经被销毁,AsyncTask的后台线程还在执行,它将继续在内存里保留这个引用,导致Activity无法被回收,引起内存泄露。

3.结果丢失:屏幕旋转或Activity在后台被系统杀掉等情况会导致Activity的重新创建,之前运行的AsyncTask会持有一个之前Activity的引用,这个引用已经无效,这时调用onPostExecute()再去更新界面将不再生效。

4.并行or串行:在Android 1.6之前的版本,AsyncTask是串行的,在1.6至2.3的版本,改成了并行的。在2.3之后的版本又做了修改,可以支持并行和串行,当想要串行执行时,直接执行execute()方法,如果需要并行执行,则要执行executeOnExecutor(Executor)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值