浅谈Android多线程编程

来源:互联网 发布:淘宝好友在哪里看 编辑:程序博客网 时间:2024/05/21 10:37

      进来这里的朋友相信是有Java线程基础的,当然,可以点击(浅谈Java多线程)回去叙叙旧。废话不多说,其实,Android多线程编并不比Java多线程编程特殊,基本都是使用相同的语法。不同的是Android多线程编程自己搞出了一套异步消息处理机制。还是先来回忆一下Java线程的基本使用吧!

//Java两种创建线程的方法//创建一个类继承Threadclass MyThread extends Thread{    @Override    public void run() {        //处理具体的逻辑    }}//启动线程//new MyThread().start();//更多时候我们会选择使用实现Runnable接口来定义一个线程class MyThread implements Runnable{    @Override    public void run() {        //处理具体的逻辑    }}//启动线程MyThread myThread=new MyThread();new Thread(myThread).start();//当然,这里也有偷懒的秘籍,如果你不想专门再定义一个类去//实现Runnable接口,也可以使用匿名类的方式(很常见的写法)。new Thread(new Runnable(){    @Override    public void run() {        //处理具体的逻辑    } }).start();
      线程在Java中是处理一些耗时操作、异步、多任务下载等等。线程到了Android这个环境以后有了新的变化,Android使用线程更多的是为了用户有更好的体验,用户是有脾气的,他们不想等、不愿去思考、还不耐烦。还有就是Android在子线程中更新UI和Java更新UI有所不同。在Android SDK提供的API中,Google进行了多次封装,因此在Android里面是不能直接通过子线程去操作UI控件的,因为在Android框架里,线程是不安全的。为了解决这个问题,官方建议我们通过这Handler个类去实现UI更新。为了更好的理解,来个例子吧!在Android平台通过子线程更新UI界面:
package com.xhm.demo.providertestling;import android.app.Activity;import android.os.Bundle;import android.widget.ImageView;/** * Created by Dell on 2017/4/16. */public class MyThread extends Activity {    private ImageView mImageView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_handler);        mImageView=(ImageView) findViewById(R.id.imageView);        new Thread(new Runnable() {            @Override            public void run() {                try{                    //休眠三秒后切换墙纸                    Thread.sleep(3000);                }catch (InterruptedException e){                    e.printStackTrace();                }                mImageView.setBackgroundResource(R.drawable.bi3);            }        }).start();    }}
布局里就一个控件,不贴代码咯!然后运行之后看到报错(程序崩溃),这样可以看出Android确实不允许在子线程中去更新UI操作的。

不着急!我们先来学习异步消息处理机制。
       Android中的异步消息处理主要由4个部分组成:Handler、Message、MessageQueue、Looper。
1.HandlerHandler顾名思义就是处理者的意思,Handler在android里负责发送和处理消息,通过它可以实现其他线程与Main线程之间的消息通讯。发送消息是使用Handler的sendMessage()方法,而发出去的消息经过一系列的辗转处理后,最终又传递到Handler的handleMessage()方法中。
2.MessageMessage是线程间通讯的消息载体。它可以携带少量的信息,用于在不同线程之间交换数据。
3.MessageQueue:MessageQueue是消息队列,先进先出,它的作用是保存有待线程处理的消息,也就是用于存放所有通过Handler发送的消息。这部分消息一直存放于消息列队中,等待被处理,每个线程只会有一个MessageQueue对象。
4.LooperLooper是每个线程中的MessageQueue管家,Looper负责管理线程的消息队列和消息循环。每个线程也只有一个Looper对象。
异步消息处理流程图:

好了,时候把上面的错误修改下咯!
package com.xhm.demo.projiect00;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.widget.Button;import android.widget.ImageView;public class MainActivity extends Activity {    private ImageView mImageView;    private static final int MESSAGE_ID=0x00000001;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mImageView=(ImageView) findViewById(R.id.imageView);        Button button=(Button) findViewById(R.id.buttons);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //创建一个子线程                new Thread(new Runnable() {                    @Override                    public void run() {                        try{                            //休眠三秒后切换墙纸                            Thread.sleep(3000);                        }catch (InterruptedException e){                            e.printStackTrace();                        }                        //通过mHandler对象的obtainMessage()                        //方法得到一个消息msg对象实例                        Message msg=mHandler.obtainMessage();                        //封装消息ID                        msg.what=MESSAGE_ID;                        //通过mHandler对象将消息发送出去                        mHandler.sendMessage(msg);                    }                }).start();            }        });    }    //创建一个Handler局部类对象    Handler mHandler=new Handler(){        @Override        public void handleMessage(Message msg) {            //得到封装的消息ID进行匹配            if (MESSAGE_ID==msg.what){                //更换ImageView的背景                mImageView.setBackgroundResource(R.drawable.bi3);            }        }    };}
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <Button        android:id="@+id/buttons"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="换墙纸"/>    <ImageView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/imageView"        android:background="@drawable/bi2"/></LinearLayout>

效果图从左到右。当然,除了切换墙纸外,计时器也是一个很好的例子,这个作业交给大家咯!好好写代码。

Handler.post:
       handle的post方法也可以用来更新UI组件,因为handler的post方法也是在主线程运行的;使用实例代码如下:
Handler mHandler = new Handler();//首先创建一个Handler对象private void initHandle() {    mThread=new Thread(new Runnable() {        @Override        public void run() {            try {                Thread.sleep(5000);//阻塞5                  mHandler.post(new Runnable() {                    @Override                    public void run() {                        //更新墙纸                          mImageView.setBackgroundResurce(R.drawable.bi3);                    }                });            } catch (Exception e) {                e.printStackTrace();            }        }    });//.start()}
使用的时候在onCreate()方法或者需要的地方调用initHandle()即可。

Handler.postDelayed:
      postDelayed和post方法大同小异,只是postDelayed比post高级一些,写法也简单一些。请看代码,一看便知。
//首先还是需要创建一个Handler对象Handler mHandler=new Handler();//这是一个类,当然,你可以写成一个方法,比如:Runnable mRunnable=new Runnable(){}private class mRunnable implements Runnable {     @Override     public void run() {         //更新墙纸          mImageView.setBackgroundResurce(R.drawable.bi3);     }}//这是调用postDelayed,意思是每隔五秒执行run方法//post一样,在onCreate()方法或者你需要的地方调用mHandler.postDelayed(new mRunnable(),5000);//那么,如果你不想用了,可以这样操作mHandler.removeCallbacks(runnable); 

最后:
      最后我们来一点题外话(其实是干货),扩展运动哈!话说没过几秒更新墙纸这种活,java里有个更简单的方法,我也是后来才知道的哈!往下看:
TimerTask task = new TimerTask() {    public void run() {        //execute the task        //更新墙纸        mImageView.setBackgroundResurce(R.drawable.bi3);    }};Timer timer = new Timer();//这里的意思是,从现在开始,每隔5秒执行此方法;简单的说,相当于定时器timer.schedule(task, 5000);
好了,如果大家还有好的方法,不妨留下言,当当雷锋也是不错啊! 谢谢!

0 0