首页 > 程序开发 > 移动开发 > Android >

Android多线程及Handler使用

2016-08-26

当我们需要执行一些耗时操作,比如说发起一条网络请求时,考虑到网速等其他原因,服务器未必会立刻响应我们的请求,如果不将这类操作放在子线程里去运行,就会导致主线程被阻塞住,从而影响用户对软件的正常使用

当我们需要执行一些耗时操作,比如说发起一条网络请求时,考虑到网速等其他原因,服务器未必会立刻响应我们的请求,如果不将这类操作放在子线程里去运行,就会导致主线程被阻塞住,从而影响用户对软件的正常使用

开启子线程

Android多线程编程其实并不比Java多线程编程特珠,基本都是使用相同的语法。比如说,定义一个线程只需要新建一个类继承自Thread,然后重写父类的run()方法,并在里面编写耗时逻辑即可,如下所示:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //启动这个线程
        new MyThread().start();
    }
    class MyThread extends Thread{
        @Override
        public void run() {
            super.run();
        }
    }

当然,使用继承的方式耦合性有点高,更多的时候我们都会选择使用实现Runnable接口的方式来定义一个线程,如下所示:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MyThread myThread = new MyThread();
        new Thread(myThread).start();
    }
    class MyThread implements Runnable {

        @Override
        public void run() {
            // 处理具体的逻辑
        }
    }

可以看到,Thread的构造函数接收一个Runnable参数,而我们new出的MyThread正是一个实现了Runnable接口的对象,所以可以直接将它传入到Thread的构造函数里。接着调用Thread的start()方法,run()方法中的代码就会在子线程当中运行了。
当然,如果你不想专门再定义一个类去实现Runnable接口,也可以使用匿名类的方式,这种写法更为常见,如下所示:

new Thread(new Runnable() {

    @Override
    public void run() {
        // 处理具体的逻辑
    }

}).start();

以上几种线程的使用方式相信你都不会感到陌生,因为在Java中创建和启动线程也是使用同样的方式。

更新UI之Handler

Handler的主要作用是在工作线程中发送消息和在UI线程中获取、处理消息。
一个Handler允许发送和处理Message或者Runnable对象

Post:Post允许把一个Runnable对象入队到消息队列中。它的方法有:
post(Runnable r) postAtTime(Runnable,long) -在特定的时间执行 postDelayed(Runnable,long) -延迟delayMills秒执行

注意 对于Post方式而言,它其中Runnable对象的run()方法的代码,均执行在UI线程上,里面不能有耗时操作

sendMessage: sendMessage允许把一个包含消息数据的Message对象压入到消息队列中。它的方法有:

sendEmptyMessage(int) -发送一个空的Message对象 sendMessageAtTime(Message,long) -在UI线程取到消息后,延迟执行 sendMessageDelayed(Message,long)。-空的Message对象,在UI线程取到消息后,延迟执行

这方面的更多资料请看http://www.cnblogs.com/shirley-1019/p/3557800.html

简单的延时进度示例

这里用到了一个handler的post方式
对于Handler的Post方式来说,它会传递一个Runnable对象到消息队列中

ProgressBar bar = (ProgressBar) findViewById(R.id.bar);
.....
public void click2(View view) {

        final Handler handler =new Handler();

        Runnable runnable =new Runnable() {
            @Override
            public void run() {
                pro =bar.getProgress()+5;
                bar.setProgress(pro);
                handler.postDelayed(this,100);
            }
        };
        handler.postDelayed(runnable,1000);
    }

当然你也可以这样写更加简便

ProgressBar bar = (ProgressBar) findViewById(R.id.bar);
.....
public void click2(View view) {

   final Handler handler =new Handler();

   handler.postDelayed(new Runnable() {
            @Override
            public void run() {
               pro =bar.getProgress()+5;
               bar.setProgress(pro);
               handler.postDelayed(this,100);
            }
        }, 1000);
   }

handleMessage处理消息

sendMessage允许把一个包含消息数据的Message对象压入到消息队列中

public class HandlerTest extends Activity {

    public static final int UPDATE_TEXT = 1;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UPDATE_TEXT:
                    // 在这里可以进行UI操作
                    //比如 text.setText(msg.getData().getString("time"));
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        new Thread(new Runnable() {
            @Override
            public void run() {

                Message message = new Message();
                message.what = UPDATE_TEXT;
                handler.sendMessage(message); // 将Message对象发送出去

                /*String time=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date());
                Message message = Message.obtain();
                Bundle bundle=new Bundle();
                bundle.putString("time",time);
                message.setData(bundle);//bundle传值,耗时,效率低
                handler.sendMessage(message);//发送message信息
                message.what=1;//标志是哪个线程传数据
                //message有四个传值方法,
                //两个传int整型数据的方法message.arg1,message.arg2
                //一个传对象数据的方法message.obj
                //一个bandle传值方法*/
            }
        }).start();
    }
}

这里写图片描述


在子线程更新UI简便方法

因为runOnUiThread工作在主线程里

  runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                      //更新UI操作  
                    }
                });
相关文章
最新文章
热点推荐