效果图:

  

1、activity_main.xml

  描述:定义了六个按钮

    

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/activity_main"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical"
  7. >
  8.  
  9. <TextView
  10. android:id="@+id/showNumber"
  11. android:textSize="35dp"
  12. android:gravity="center"
  13. android:layout_width="match_parent"
  14. android:layout_height="wrap_content"
  15. android:text="0"
  16. />
  17. <LinearLayout
  18. android:layout_width="match_parent"
  19. android:layout_height="wrap_content"
  20. android:orientation="horizontal"
  21. >
  22. <Button
  23. android:layout_width="match_parent"
  24. android:layout_height="wrap_content"
  25. android:text="开始计数"
  26. android:onClick="doStart"
  27. android:layout_weight="1"
  28. />
  29. <Button
  30. android:layout_width="match_parent"
  31. android:layout_height="wrap_content"
  32. android:text="结束计数"
  33. android:onClick="doStop"
  34. android:layout_weight="1"
  35. />
  36. <Button
  37. android:layout_width="match_parent"
  38. android:layout_height="wrap_content"
  39. android:text="开始计数2"
  40. android:onClick="doStart2"
  41. android:layout_weight="1"
  42. />
  43. <Button
  44. android:layout_width="match_parent"
  45. android:layout_height="wrap_content"
  46. android:text="结束计数2"
  47. android:onClick="doStop2"
  48. android:layout_weight="1"
  49. />
  50. </LinearLayout>
  51. <Button
  52. android:layout_width="match_parent"
  53. android:layout_height="wrap_content"
  54. android:text="子线程和子线程之间的通信"
  55. android:onClick="test_1"
  56. />
  57. <Button
  58. android:layout_width="match_parent"
  59. android:layout_height="wrap_content"
  60. android:text="异步任务"
  61. android:onClick="test_2"
  62. />
  63. </LinearLayout>

2、MainActivity.java

  1. package com.nf.android_thread;
  2.  
  3. import android.app.Activity;
  4. import android.content.Intent;
  5. import android.os.Bundle;
  6. import android.os.Handler;
  7. import android.os.Message;
  8. import android.os.SystemClock;
  9. import android.view.View;
  10. import android.widget.TextView;
  11. import android.widget.Toast;
  12.  
  13. public class MainActivity extends Activity {
      //用来显示数字
  14. private TextView showNumber;
  15. @Override
  16. protected void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. setContentView(R.layout.activity_main);
  19. showNumber = (TextView)findViewById(R.id.showNumber);
  20.      //弹出提示
  21. Toast.makeText(this,"程序开始",Toast.LENGTH_SHORT).show();
  22. //将耗时操作放到子线程中,将不会阻塞主线程运行
  23. new Thread(new Runnable() {
  24. @Override
  25. public void run() {
  26. try{
                //线程休眠20秒
  27. Thread.currentThread().sleep(20000);
  28. }catch (InterruptedException e){
  29. e.printStackTrace();
  30. }
  31. }
  32. }).start();
  33. Toast.makeText(this,"程序结束",Toast.LENGTH_SHORT).show();
  34. }
  35. //声明一个主线程的Handler对象
      /*
        handler:
        消息的封装者和处理者,handler负责将需要传递的信息封装成Message,通过调用handler对象的obtainMessage()来实现;
        将消息传递给Looper,这是通过handler对象的sendMessage()来实现的。继而由Looper将Message放入MessageQueue中。
        当Looper对象看到MessageQueue中含有Message,就将其广播出去。
        该handler对象收到该消息后,调用相应的handler对象的handleMessage()方法对其进行处理。
      
      */
      /*
        Message:
        消息对象,Message Queue中的存放的对象。一个Message Queue中包含多个Message。
        Message实例对象的取得,通常使用Message类里的静态方法obtain(),该方法有多个重载版本可供选择;
        它的创建并不一定是直接创建一个新的实例,而是先从Message Pool(消息池)中看有没有可用的Message实例,存在则直接取出返回这个实例。
        如果Message Pool中没有可用的Message实例,则才用给定的参数创建一个Message对象。
        调用removeMessages()时,将Message从Message Queue中删除,同时放入到Message Pool中。
        除了上面这种方式,也可以通过Handler对象的obtainMessage()获取一个Message实例。
      */
      /*
        MessageQueue
        是一种数据结构,见名知义,就是一个消息队列,存放消息的地方。每一个线程最多只可以拥有一个MessageQueue数据结构。
        创建一个线程的时候,并不会自动创建其MessageQueue。通常使用一个Looper对象对该线程的MessageQueue进行管理。
        主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个Message Queue。
        其他非主线程,不会自动创建Looper,要需要的时候,通过调用prepare函数来实现。
      */
      /*
        Looper:
        是MessageQueue的管理者。每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的。
        同时每一个Looper对象和一个线程关联。通过调用Looper.myLooper()可以获得当前线程的Looper对象创建一个Looper对象时,会同时创建一个MessageQueue对象。
        除了主线程有默认的Looper,其他线程默认是没有MessageQueue对象的,所以,不能接受Message。
        如需要接受,自己定义一个Looper对象(通过prepare函数),这样该线程就有了自己的Looper对象和MessageQueue数据结构了。
        Looper从MessageQueue中取出Message然后,交由Handler的handleMessage进行处理。
        处理完成后,调用Message.recycle()将其放入Message Pool中。
      */
  36. private Handler handler = new Handler(){
  37. @Override
  38. public void handleMessage(Message msg){
  39. super.handleMessage(msg);
           //判断来自哪个线程的handler
  40. if (msg.what == 1){
              //给ui控件绑定计算得到的数字
  41. showNumber.setText(msg.arg1+"");
  42. }
  43. }
  44. };
  45. //开始计数
  46. int number = 1;
  47. boolean isRun;
  48. public void doStart(View view){
  49. isRun = true;
  50. new Thread(new Runnable() {
  51. @Override
  52. public void run() {
  53. while (isRun){
  54. //将计数发送给UI线程【Main Thread】
                // 这里的数据data我们必须发送给UI的主线程,所以我们通过Message的方式来做桥梁。
  55. Message message = Message.obtain();
                //设置handler版本
  56. message.what = 1;
  57. message.arg1 = number;
  58. //如果将消息发给主线程呢
                //调用handler的sendMessage()方法,将得到的数字传进去
  59. handler.sendMessage(message);
  60. SystemClock.sleep(1000);
  61. number++;
  62. }
  63. }
  64. }).start();
  65. }
       //当点击停止按钮时,将isRun设置为false,并将number设置为1
  66. public void doStop(View view){
  67. isRun = false;
  68. number = 1;
  69. }
  70.  
  71. public void doStart2(View view){
  72. isRun = true;
  73. new Thread(new Runnable() {
  74. @Override
  75. public void run() {
  76. while (isRun){
  77. //UI多线程中不能直接更新UI
  78. runOnUiThread(new Runnable() {
  79. @Override
  80. public void run() {
  81. showNumber.setText(number+"");
  82. }
  83. });
  84. number++;
  85. SystemClock.sleep(1000);
  86. }
  87. }
  88. }).start();
  89. }
  90. public void doStop2(View view){
  91. doStop(view);
  92. }
  93.  
  94. public void test_1(View view){
  95. Intent intent = new Intent(this,Thread2Activity.class);
  96. startActivity(intent);
  97. }
  98. public void test_2(View view){
  99. Intent intent = new Intent(this,AsyncTaskActivity.class);
  100. startActivity(intent);
  101. }
  102. }

3、activity_thread2.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/activity_thread2"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical"
  7. >
  8. <TextView
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:id="@+id/showNumber"
  12. android:text="0"
  13. android:textSize="40dp"
  14. android:gravity="center"
  15. />
  16. <Button
  17. android:layout_width="match_parent"
  18. android:layout_height="wrap_content"
  19. android:text="开始计算"
  20. android:onClick="doStart"
  21. />
  22. <Button
  23. android:layout_width="match_parent"
  24. android:layout_height="wrap_content"
  25. android:text="停止计算"
  26. android:onClick="doStop"
  27. />
  28. </LinearLayout>

4、Thread2Activity.java

  1. package com.nf.android_thread;
  2.  
  3. import android.app.Activity;
  4. import android.app.Notification;
  5. import android.os.Bundle;
  6. import android.os.Handler;
  7. import android.os.Looper;
  8. import android.os.Message;
  9. import android.os.SystemClock;
  10. import android.util.Log;
  11. import android.view.View;
  12. import android.widget.TextView;
  13.  
  14. import java.util.Random;
  15.  
  16. public class Thread2Activity extends Activity {
  17. private TextView showNumber;
  18. @Override
  19. protected void onCreate(Bundle savedInstanceState) {
  20. super.onCreate(savedInstanceState);
  21. setContentView(R.layout.activity_thread2);
  22. showNumber = (TextView)findViewById(R.id.showNumber);
  23. }
      
  24. private Handler mainHandler = new Handler(){
  25. @Override
  26. public void handleMessage(Message msg){
  27. super.handleMessage(msg);
  28. if (msg.what == 2){
  29. showNumber.setText(msg.arg1+"");
  30. }
  31. }
  32. };
  33.  
  34. boolean isRun;
  35. int count = 0;
  36. Handler myHandler;
  37. public void doStart(View view){
  38. //用来处理数字平方的线程
  39. new Thread(new Runnable() {
  40. @Override
  41. public void run() {
              //Android中的Looper类,是用来封装消息循环和消息队列的一个类,用于在android线程中进行消息处理。
              //handler其实可以看做是一个工具类,用来向消息队列中插入消息的。
  42. Looper.prepare();//准备好一个消息队列
  43. myHandler = new Handler(){
  44. @Override
  45. public void handleMessage(Message msg){
  46. super.handleMessage(msg);
  47. if (msg.what==1){
  48. Log.i("Thread2:","消息:"+msg.arg1);
  49. int number = msg.arg1*msg.arg1;
  50. Message message = Message.obtain();
  51. message.what = 2;
  52. message.arg1 = number;
  53. mainHandler.sendMessage(message);
  54. }
  55. }
  56. };
  57. Looper.loop();//循环
  58. }
  59. }).start();
  60. //开始计数的线程
  61. isRun = true;
  62. new Thread(new Runnable() {
  63. @Override
  64. public void run() {
  65. while (isRun){
  66. int rand = new Random().nextInt(100);//获得随机数
  67. Log.i("Thread1:","随机数:"+rand);
  68. //发生消息到处理数字的线程
  69. Message msg = Message.obtain();
  70. msg.what = 1;
  71. msg.arg1 = rand;
  72. myHandler.sendMessage(msg);//通过Handler将消息发送到线程2
  73. count++;
  74. if (count>100)
  75. break;
  76. SystemClock.sleep(1000);
  77. }
  78. }
  79. }).start();
  80. }
  81. public void doStop(View view){
  82. isRun = false;
  83. count = 0;
  84. }
  85. }

5、activity_async_task.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/activity_async_task"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical"
  7. >
  8. <ProgressBar
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:id="@+id/progressBar"
  12. style="@android:style/Widget.ProgressBar.Horizontal"
  13. />
  14. <Button
  15. android:layout_width="match_parent"
  16. android:layout_height="wrap_content"
  17. android:text="开始下载"
  18. android:onClick="doStart"
  19. />
  20. <Button
  21. android:layout_width="match_parent"
  22. android:layout_height="wrap_content"
  23. android:text="结束下载"
  24. android:onClick="doStop"
  25. />
  26. </LinearLayout>

6、AsyncTaskActivity.java

  1. package com.nf.android_thread;
  2.  
  3. import android.app.Activity;
  4. import android.content.Intent;
  5. import android.os.AsyncTask;
  6. import android.os.Bundle;
  7. import android.os.SystemClock;
  8. import android.view.View;
  9. import android.widget.ProgressBar;
  10. import android.widget.Toast;
  11.  
  12. public class AsyncTaskActivity extends Activity {
      //进度条
  13. private ProgressBar progressBar;
  14. @Override
  15. protected void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.activity_async_task);
  18. progressBar =(ProgressBar)findViewById(R.id.progressBar);
  19. }
  20.  
  21. MyAsyncTask task;
  22. //开启一个异步任务执行下载
  23. public void doStart(View view){
         //当点击开始按钮后,实例化一个异步任务
  24. task = new MyAsyncTask();
          
  25. task.execute(0);
  26. }
  27.  
  28. //结束异步下载任务
  29. public void doStop(View view){
  30. task.cancel(true);
  31. }
  32.  
  33. //构建一个异步任务
  34. class MyAsyncTask extends AsyncTask<Integer,Integer,String>{
  35. //必须的,执行异步操作
         //属于后台操作
         /**  
            * 这里的Integer参数对应AsyncTask中的第一个参数   
            * 这里的String返回值对应AsyncTask的第三个参数  
          * 该方法并不运行在UI线程当中,主要用于异步操作,所有在该方法中不能对UI当中的空间进行设置和修改  
          * 但是可以调用publishProgress方法触发onProgressUpdate对UI进行操作  
          */  
  1. @Override
  2. protected String doInBackground(Integer...integers){
  3. for (int i=1;i<100;i++){
  4. publishProgress(i);//刷新进度
  5. SystemClock.sleep(100);
  6. }
  7. return "success";
  8. }
  9.      //做一些初始化的操作
         //该方法运行在UI线程当中,并且运行在UI线程当中 可以对UI空间进行设置  
  10. @Override
  11. protected void onPreExecute(){
  12. super.onPreExecute();
  13. Toast.makeText(AsyncTaskActivity.this,"开始下载",Toast.LENGTH_SHORT).show();
  14. }
  15.      //得到后台操作返回的结果
        /**  

    * 这里的String参数对应AsyncTask中的第三个参数(也就是接收doInBackground的返回值)

   * 在doInBackground方法执行结束之后在运行,并且运行在UI线程当中 可以对UI空间进行设置

  */

  1. @Override
  2. protected void onPostExecute(String s){
  3. super.onPostExecute(s);
  4. if ("success".equals(s)){
  5. Toast.makeText(AsyncTaskActivity.this,"下载完毕",Toast.LENGTH_SHORT).show();
  6. }else{
  7. Toast.makeText(AsyncTaskActivity.this,"下载失败",Toast.LENGTH_SHORT).show();
  8. }
  9. }
         //更新进度
         

      /**

    * 这里的Intege参数对应AsyncTask中的第二个参数

    * 在doInBackground方法当中,每次调用publishProgress方法都会触发onProgressUpdate执行

    * onProgressUpdate是在UI线程中执行,所以可以对UI空间进行操作

    */

  1. @Override
  2. protected void onProgressUpdate(Integer... values){
  3. super.onProgressUpdate(values);
  4. //更新进度条
  5. progressBar.setProgress(values[0]);
  6. }
  7. }
  8. }

Android开发 ---多线程操作:Handler对象,消息队列,异步任务下载的更多相关文章

  1. Android开发---如何操作资源目录中的资源文件4 ---访问xml的配置资源文件的内容

    Android开发---如何操作资源目录中的资源文件4 XML,位于res/xml/,这些静态的XML文件用于保存程序的数据和结构. XmlPullParser可以用于解释xml文件 效果图: 描述: ...

  2. Android开发---如何操作资源目录中的资源文件3--圆角边框、背景颜色渐变效果、边框颜色

    Android开发---如何操作资源目录中的资源文件3 效果图 1.圆角边框 2.背景颜色渐变效果 1.activity_main.xml 描述: 定义了一个shape资源管理按钮 <?xml ...

  3. Android开发 ---如何操作资源目录中的资源文件2

    Android开发 ---如何操作资源目录中的资源文件2 一.颜色资源管理 效果图: 描述: 1.改变字体的背景颜色 2.改变字体颜色 3.改变按钮颜色 4.图像颜色切换 操作描述: 点击(1)中的颜 ...

  4. Java多线程操作同一个对象,线程不安全

    Java多线程操作同一个对象 发现问题:多个线程操作同一资源的情况下,线程不安全,数据紊乱 代码: package multithreading; // Java多线程操作同一个对象 // 买火车票的 ...

  5. Android开发——通过扫描二维码,打开或者下载Android应用

    Android开发——通过扫描二维码,打开或者下载Android应用   在实现这个功能的时候,被不同的浏览器折磨的胃疼,最后实现了勉强能用,也查考了一下其他人的博客 android实现通过浏览器点击 ...

  6. Android开发笔记之:Handler Runnable与Thread的区别详解

    在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类是在java.lang包中定义的.一 个类只要继承了Thread类同时覆写了本类中的run( ...

  7. Android开发 之 理解Handler、Looper、MessageQueue、Thread关系

    本文转自博客:http://blog.csdn.net/he90227/article/details/43567073 一. 图解与概述 首先Android中 的每一个线程都会对应一个Message ...

  8. Android开发手记(28) Handler和Looper

    Android的消息处理有三个核心类:Looper,Handler和Message.其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了,我们不会直接与MQ打交道.平 ...

  9. 【转】Android开发实践:自定义带消息循环(Looper)的工作线程

    http://ticktick.blog.51cto.com/823160/1565272 上一篇文章提到了Android系统的UI线程是一种带消息循环(Looper)机制的线程,同时Android也 ...

随机推荐

  1. HTML和CSS总结

    语义化.我们学习网页制作时,常常会听到一个词,语义化.那么什么叫做语义化呢,说的通俗点就是:明白每个标签的用途(在什么情况下使用此标签合理)比如,网页上的文章的标题就可以用标题标签,网页上的各个栏目的 ...

  2. AARRR海盗模型简介

    整理下AARRR模型的概念.实际应用场景等问题,初步感觉这个模型主要应用在APP应用分析中. 1.什么是AARRR模型 AARRR是Acquisition.Activation.Retention.R ...

  3. jw player 配置参数

    Loading the player … //player所在div //具体配置参数 jwplayer(“container”).setup({//通过js调用播放器并安装到指定容器(contain ...

  4. Jmeter接口测试+压力测试+环境配置+证书导出

    jmeter是apache公司基于java开发的一款开源压力测试工具,体积小,功能全,使用方便,是一个比较轻量级的测试工具,使用起来非常简单.因为jmeter是java开发的,所以运行的时候必须先要安 ...

  5. codeforces #305 E Mike and friends

    原问题可以转化为:给定第k个字符串,求它在L-R的字符串里作为子串出现了多少次 定义子串为字符串的某个前缀的某个后缀(废话) 等价于我们把一个字符串插入到trie里,其过程中每个经过的节点和其向上的f ...

  6. jquery简易tab切换

    切换tab 使用eq()函数 eq() 方法将匹配元素集缩减值指定 index 上的一个. //为项目 3 设置红色背景 <ul> <li>list item 1</li ...

  7. SSM-网站后台管理系统制作(4)---Ajax前后端交互

    前提:Ajax本身就为前后端交互服务的,实现功能:用户输入信息,实时判断用户的情况,这也是现在登录界面普遍流行的做法.前端js通过注释识别Controller层,该层查询返回,和之前Google验证码 ...

  8. [译]Quartz.NET 3.x 教程

    译者注: 最近有点小浮躁,找点事做做平静下内心的焦作,干脆翻译下 Quartz.NET 3.x Tutorial 好了. Quartz.NET 3.x 教程 选择课程:带划线的表示没完成 课程 1: ...

  9. --save 与--save-dev的区别

    一.模式 运行webpack命令时,一定要指定模式. webpack --mode developmentwebpack --mode production二.--save -dev --save:将 ...

  10. 表单提交:button input submit 的区别

    http://harttle.com/2015/08/03/form-submit.html 最近项目代码中的表单提交的方式已经百花齐放了,现在用这篇文章来整理一下不同表单提交方式的区别,给出最佳实践 ...