Android 理解多线程

安卓应用程序通常是应用在一个单独的线程里的,即为主线程,用于显示用户界面以及响应用户的操作。
如果一些耗时任务也同时在主线程里去完成,则会影响用户体验,会阻塞UI主线程。我们会创建一个单独的线程或者子线程,去处理这些耗时操作(如网络请求、数据库操作等)。
那么这些子线程就是AsyncTask、Thread、HandlerThread,它们叫做安卓的工作者线程。
- AsyncTask
- Handler


一、AsyncTask异步任务

AsyncTask是Android的一个轻量级异步类,可以自定义类并继承AsyncTask,实现异步任务处理操作。并且AsyncTask提供了接口返回异步操作的进度,最后会返回结果到UI主线程中。

优点:简单快捷,过程可以控制
缺点:在处理多个异步操作时比较复杂

参数 说明
Params 启动任务时输入的执行参数,一般为一个网络地址
Progress 异步任务执行的进度
Result 异步任务执行后的结果的类型

代码实例

这是一个利用AsyncTask加载网络图片的代码:

public class MainActivity extends ActionBarActivity
{
private Button button1;
private ImageView imageview1;
private ProgressDialog dialog;

private String image_uri =”https://imgsa.baidu.com/baike/c0%3Dbaike272%2C5%2C5%2C272%2C90/sign=c4f298bb97ef76c6c4dff379fc7f969f/9358d109b3de9c82f077b3156b81800a19d8431d.jpg”;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dialog = new ProgressDialog(this);
dialog.setTitle(“图片下载”);
dialog.setMessage(“正在下载,请稍后…”);
button1 = (Button) findViewById(R.id.button1);
imageview1 = (ImageView) findViewById(R.id.imageView1);
button1.setOnClickListener(new OnClickListener()
{

        @Overridepublic void onClick(View v){// TODO Auto-generated method stubnew DownloadTask().execute(image_uri);}});
}//自定义下载类继承AsyncTask
public class DownloadTask extends AsyncTask<String, Void, Bitmap>
{// 这个方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等。@Overrideprotected void onPreExecute(){// TODO Auto-generated method stubdialog.show();super.onPreExecute();}// 这个方法中的所有代码都会在子线程中运行,主要完成耗时任务// 注意,在这个方法中是不可以进行UI操作的//在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。@Overrideprotected Bitmap doInBackground(String... params){// TODO Auto-generated method stub// 使用网络链接类HttpClient完成网络数据的获取HttpClient httpClient = new DefaultHttpClient();HttpGet httpGet = new HttpGet(params[0]);Bitmap bitmap = null;try{HttpResponse httpResponse = httpClient.execute(httpGet);if (httpResponse.getStatusLine().getStatusCode() == 200){HttpEntity httpEntity = httpResponse.getEntity();byte[] data = EntityUtils.toByteArray(httpEntity);bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);}} catch (Exception e){// TODO: handle exceptione.printStackTrace();}return bitmap;}//在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。@Overrideprotected void onProgressUpdate(Void... values){// TODO Auto-generated method stubsuper.onProgressUpdate(values);}// 可以利用返回的数据来进行一些UI操作,比如说提醒任务执行的结果,以及关闭掉进度条对话框等。protected void onPostExecute(Bitmap result){// TODO Auto-generated method stubsuper.onPostExecute(result);imageview1.setImageBitmap(result);dialog.dismiss();}
}

}

参考:android AsyncTask介绍
详解Android中AsyncTask的使用

二、Handler

1、Handler概念:

I 、Handler 是 Android 给我们提供来更新 UI 的一套机制,也是一套消息处理的机制,我们可以发送消息,也可以通过它来处理消息。
II、Android 在设计的时候,就封装了一套消息创建、传递、处理机制,如果不遵循这样的机制就没有办法更新 UI 信息,就会抛出异常信息。

2、与Handler相关的几个概念:

I、Message 消息,理解为线程间通讯的数据单元。例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程。
II、Message Queue 消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
III、Handler Handler是Message的主要处理者,负责将Message添加到消息队列以及对消息队列中的Message进行处理。
Looper 循环器,扮演Message Queue和Handler之间桥梁的角色,循环取出Message Queue里面的Message,并交付给相应的Handler进行处理。
IV、线程 UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。

3、Handler的一些分发消息的方法

    post(Runnable)postAtTime(Runnable,long)postDelayed(Runnable long)sendEmptyMessage(int)sendMessage(Message)sendMessageAtTime(Message,long)sendMessageDelayed(Message,long)

4、关于Message

创建Handler实例,要重载handleMessage方法,来处理消息
获取Message对象的最好方法是调用Message.obtain()

Message可传递的参数:

①. arg1 arg2 整数类型,是setData的低成本替代品,传递简单类型。
Object 类型 obj
②. what 用户自定义的消息代码,这样接受者可以了解这个消息的信息。每个handler各自包含自己的消息代码,所以不用担心自定义的消息跟其他handlers有冲突
③.其他的可以通过Bundle进行传递
Message可以通过new Message构造来创建一个新的Message,但是这种方式很不好,不建议使用。最好使用Message.obtain()来获取Message实例,它创建了消息池来处理的。

5、代码实例
利用Handler创建一个dialog进度条并显示进度

public class HandlerActivity extends Activity
{
private Button button1;
private static ProgressDialog dialog;
//创建Handler静态对象
private static Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
int index=msg.arg1;
dialog.setProgress(index);
if (msg.what==1)
{
dialog.dismiss();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
button1=(Button)findViewById(R.id.button1);
dialog=new ProgressDialog(this);
dialog.setTitle(“正在下载…”);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
button1.setOnClickListener(new OnClickListener()
{

        @Overridepublic void onClick(View v){// TODO Auto-generated method stubnew Thread(new MyThread()).start();dialog.show();}});
}
//创建一个子线程继承Runnable
public class MyThread implements Runnable{int count=1;int index=0;@Overridepublic void run(){// TODO Auto-generated method stubwhile(count<=100){try{Thread.sleep(200);} catch (Exception e){// TODO: handle exceptione.printStackTrace();}Message message=Message.obtain();message.arg1=count;handler.sendMessage(message);count++;}Message end=Message.obtain();end.what=1;handler.sendMessage(end);}
}

参考:Android中的Handler的机制与用法详解
Android中的Handler总结

Android多线程理解相关推荐

  1. android多线程的本质,[原创]分析unidbg(unidbgMutil)多线程机制

    unidbg多线程分析 一. 概述 由于在工作中遇到了某翻译so中有多线程调用,因此使用unidbg分析(基于unidbgMutilThread)并增加阻塞唤醒机制(futex系统调用),但仍未调用成 ...

  2. Android多线程源码学习笔记一:handler、looper、message、messageQueue

    最近在学习Android多线程相关知识的源码,现在把自己的笔记整理一下,写出来加深印象. Android多线程通讯的核心是handler.looper.message.messageQueue,这篇文 ...

  3. Android 系统(152)---Android多线程:HandlerThread详细使用手册

    Android多线程:HandlerThread详细使用手册 前言 多线程的应用在Android开发中是非常常见的,常用方法主要有: 继承Thread类 实现Runnable接口 Handler As ...

  4. Android 系统性能优化(45)---Android 多线程

    前言 Android 开发中多线程的必要性 理解 Android 多线程 MessageQueue Looper Handler HandlerThread Android 中为什么只允许在主线程更新 ...

  5. Android高工:细说 Android 多线程,211本硕如何通过字节跳动、百度、美团Android面试

    我们都是被圈养的人? 我的朋友程序员K,说他在电力行业的一家软件公司做了八年Android开发,用到的各种技术,数据库,网络请求,事件传递,响应框架都很熟悉,甚至JNI/NDK/Framework,J ...

  6. Android多线程机制

    问题 1)为何需要多线程? 在android中,在主线程中如果耗时太长会出现ANR(android not Responding),也就是看起来很卡: 一些下载图片,下载数据等耗时操作需要在其他线程执 ...

  7. 第十章 进程间的通信 之 Java/Android多线程开发(二)

    文章目录 (一)Java 多线程开发 1.1)线程状态 1.2)线程控制方法 (1.2.1)Synchronized (1.2.2)Volatile (1.2.3)ReentrantLock 1.3) ...

  8. Android 多线程实现方式

    该原创文章首发于微信公众号"字节流动" Android 多线程实现方式 通常来说,一个应用至少有一个进程,而一个进程至少有一个线程. 线程是 CPU 调度的基本单位,进程是系统资源 ...

  9. Android多线程(Handler篇)

    [齐天的博客]转载请注明出处(万分感谢!): https://blog.csdn.net/qijinglai/article/details/80685226 关联文章: Android多线程(Han ...

  10. Android多线程编程(一)- 线程基础

    Android多线程编程(一) 到了学习下一部分了,多线程编程一直都是Android经常使用的部份,在进行网络请求或者访问数据库时,为了避免主线程被耗时操作阻塞了进度,通常都会开启子线程进行处理,多线 ...

最新文章

  1. (C++)变长数组vector的常见用法
  2. 一文了解Kubernetes的前世今生
  3. Linux下交叉编译gdb和gdbserver
  4. jedis高版本的JedisPoolConfig没有maxActive和maxWait
  5. flex的三个属性grow、shrink、basis
  6. mac win7 计算机,详解mac如何安装win7
  7. GCC详解-Binutils工具之readelf
  8. cass转换jpg_【转】南方CASS作原有地形图数字化--对扫描栅格图像进行校正及矢量化...
  9. ppt 制作海报 导出高分辨率图片
  10. 用户增长——AARRR模型
  11. PatchMatch分析
  12. 静态文档,动态文档和活动文档
  13. 计算机组成原理中的直接映像,计算机组成原理--cache存储器的直接映像与变换...
  14. Megahit, metaSPAdes, metabat2, GTDB-tk, checkM
  15. 记录导出微信聊天记录到硬盘的过程
  16. 产品|B站2月份创作者分析
  17. Hive 分区表 分桶表
  18. 有没有u盘数据恢复软件免费版?u盘数据恢复软件哪个好?
  19. vite+ts+elementplus运行正常打包报错
  20. 面试官:线上服务CPU飙高怎么排查?

热门文章

  1. qlv转mp4出来没有画面
  2. 经常见到的几个菜谱名字
  3. UE4(Unreal Engine4)快捷键
  4. 【PA2011】Kangaroos
  5. 如何在云服务器上部署程序
  6. JavaWeb整合萤石云(一),VUE和小程序也适用
  7. 墨刀怎么注册_墨刀的使用
  8. 微信小程序发布版本之后自动更新功能
  9. python正态分布拟合曲线怎么打印出中位数值,如何用对数正态分布函数拟合数据...
  10. mbit职业测试软件,MBTI职业性格测试(最新免费版)