Android线程与消息处理机制

刚刚入门Android,感觉Android机制和Java机制有很多相同的地方,但是Android里面还是会有很多语法不一样,这里由于刚刚学过线程,通过线程机制来对这两种进行对比学习。对于已经了解Java的同学在学习Android的时候一定要与Java进行对比学习,这样不仅仅学习Android可以更快,而且可以对Java更深层次了解。

首先我们看,我们在学习Java的时候是如何创建线程的。我们用Java做线程动画的时候直接创建了一个类来继承thread类,这样在主函数中再声明这个类的对象然后调用start方法就相当于创建了一个线程。在创建的这个类中重写run()方法就可以了。
其实在Java中创建一个线程有两种方法:
1.
创建一个类继承Thread
重写Thread中的run方法 (创建线程是为了执行任务 任务代码必须有存储位置,run方法就是任务代码的存储位置。)
创建子类对象,其实就是在创建线程
启动线程start()
2.
创建实现了Runnable接口的子类
重写Runnable接口中的run方法
创建实现了Runnable接口的子类的对象
创建Thread类的对象,也就是在创建线程
把实现了Runnable接口的子类对象作为参数传递给Thread类的构造方法

那这两种方法有什么不一样呢?
从本质上进行区分第一种是通过继承一个类来实现的,我们是通过重写run方法,因此线程任务和线程是绑定在一起的,也就是说我们run方法里面写的什么,调用start方法的时候就启动的什么线程。
第二种方法把线程任务进行了描述,也就是面向对象,从而实现了线程任务和线程对象的分离。线程执行什么任务不再重要,只要是实现了Runnable接口的子类对象都可以作为参数传递给Thread的构造方法,此方式较为灵活。

其实在Android的线程和Java的线程差不多,也就是这两种方式来创建线程。这次以绘制小弹球游戏来讲解一下Android中线程的操作。
我们在创建Android线程的时候就是需要像Java那样创建一个类来继承thread类,然后调用start方法就可以了。但是我们在这里需要进行区别的就是当在Android中进行UI交互的时候,说白了就是想要改变组件的时候只能在主线程里面进行。也就是说我们之前的Java工程里面的弹球游戏在线程里面直接绘制小球,这样是会报错的,那么我们想要实现这个功能该怎么办呢。在Android中有一个handle机制专门来处理这类问题。

那么重点来了,什么是handle机制呢。我们可以这样理解:从开发角度角度来说,Handler是Android消息机制的上层接口,通过handler,可以将一个任务切换到handler所在的线程中执行,我们通常使用handler来更新UI,但更新UI仅仅是的使用场景之一,handler并不是仅仅用来更新UI。
更新UI的具体情况是这样的:和其他GUI库一样,Android的UI也是线程不安全的,也就是说想要更新应用程序中的UI元素,则必须在主线程中进行。所以主线程又叫做UI线程。若在子线程中更新UI程序会报错。因此回归到我们想要在子线程来画小球到界面上的时候就需要使用handler,将我们想要画的东西通过message传递给handler,然后让handler的处理消息机制来把我们想要的东西给画出来。这里又涉及到了message,先看一下message的源代码。

Message就是我们需要处理的消息,我们通过handler来对这些消息进行处理。那么理所当然的我们就想到这里我们就是通过message的传递来实现从子线程传递东西给主线程从而实现子线程里面的东西也可以画到UI上。
可以看到message类里面有what属性,这个属性就是为了区分message而添加的一个相当于标志位。从而在handler里面进行处理的时候可以通过what的不同来对message进行分类从而进行不同的处理。
Obj属性就是我们用来传递的中间变量。我们通过对obj的赋值来进行传递。

说完了message下面我们来看一下handler里面有哪些具体的方法来让我们实现消息的传递。
void handleMessage(Message msg):处理消息的方法。该方法在创建Handler时重写。处理消息。这个方法是最重要的一个方法,因为我们传递过来的消息改进型什么样子的处理就应该全部重写在这个方法里面。
final boolean hasMessage(int what):检查消息队列中是否包含what属性为指定值(参数中的what)的消息
final boolean hasMessage(int what,Object object):检查消息队列中是否包含what属性值为指定值且object属性值为指定对象的消息
多个重载的 Message obtainMessage():获取Message,经常用于创建一个Message对象。例如obtainMessage(int what,Object object)。
sendEmptyMessage(int what):发送空消息
final sendEmptyMessageDelayed(int what,long delayMills):指定delayMills毫秒后发送空消息。
final boolean sendMessage(Message msg):立即发送消息
final boolean sendMessageDelayed(Message msg,long delayMills):指定delayMill毫秒后发送消息

看似消息的处理很麻烦,说白了也就是不停的循环消息队列来处理消息,而子线程通过项队列里面send消息,从而达到在主线程中处理相应消息的过程。

有了这个机制之后我们的弹球动画就简单多了,但是又有一个问题出来了我们该向handler传递什么信息呢。在画弹球的时候如果我们向handler传递小球的话那么每一个小球都需要启动一个线程来进行控制这样会比较浪费资源。我们可以采用向handler传递小球队列,然后在handler处理中将队列里面的小球都取出来然后通过创建的canvas还有paint进行绘制bitmap最后显示,或者最简单直接的在子线程中直接将bitmap画好,然后将bitmap作为message.obj传递给handler,在handler中将bitmap画到相应的图形显示的地方就可以了。

Handler类:
public class DrawHandler extends Handler{

private Canvas canvas = new Canvas();
private android.widget.ImageView ivDraw;
private Paint P;
private Bitmap bitmap;

public DrawHandler(Canvas canvas,android.widget.ImageView ivDraw,Bitmap bitmap){

    this.canvas=canvas;
    this.ivDraw=ivDraw;
    this.bitmap = bitmap;
}

//消息处理的时候直接将bitmap进行显示就行了
public void handleMessage(Message msg){

    bitmap = (Bitmap)msg.obj;
    //bitmap = Bitmap.createBitmap(ivDraw.getWidth(), ivDraw.getHeight(), Bitmap.Config.ARGB_8888);
    if(bitmap!=null){

        ivDraw.setImageBitmap(bitmap);
        ivDraw.invalidate();
    }
}

}

子线程类中与Java中不同的地方就是不能直接画图而是将想要画的东西先显示在bitmap上,然后将bitmap传递给Handler这样就完成了画图。先将message取出来,然后将我们画好的bitmap作为obj传回去给handler。
Message m = handler.obtainMessage();
if(bitmap==null){
bitmap = Bitmap.createBitmap(ivDraw.getWidth(),ivDraw.getHeight(), Bitmap.Config.ARGB_8888);
}

        canvas=new Canvas(bitmap);

// ivDraw.setImageBitmap(bitmap);

        P = new Paint();
        int c = Color.rgb(0, 255, 0);
        P.setColor(c);
        //循环将队列里面的小球都画出来
        if (list1 != null) {
            for (int i = 0; i < list1.size(); i++) {
                list1.get(i).color = Color.BLUE;
                P.setColor(list1.get(i).color);
                canvas.drawCircle(list1.get(i).x, list1.get(i).y, list1.get(i).r, P);
            }
        }

// ivDraw.invalidate();

        m.obj = bitmap;
        handler.sendMessage(m);

主线程源代码:
package com.example.tank;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

import java.util.ArrayList;

public class game extends AppCompatActivity {

private android.widget.ImageView ivDraw;
private ArrayList<myTank> list1;
private Bitmap bitmap;
private Canvas canvas;
private Paint P;
private game ge = this;


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

    list1 = new ArrayList<myTank>();
    ivDraw = (ImageView)this.findViewById(R.id.ivDraw);

// if(bitmap==null){
// bitmap = Bitmap.createBitmap(ivDraw.getWidth(), ivDraw.getHeight(), Bitmap.Config.ARGB_8888);
// canvas=new Canvas(bitmap);
// ivDraw.setImageBitmap(bitmap);
// }

    DrawHandler dh=new DrawHandler(canvas,ivDraw,bitmap);

    ivDraw.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            float x = event.getX();
            float y = event.getY();
            int action = event.getAction();
            //Log.v("DrawActivity", "x:" + x + "y:" + y + "action" + action);

            if(event.getAction()==MotionEvent.ACTION_DOWN){

// canvas.drawCircle(x,y,60,P);
// ivDraw.invalidate();
myTank my = new myTank(ge,x,y,60);
list1.add(my);
}
return false;
}
});

    pthread dt=new pthread(dh,ivDraw,list1,bitmap);
    dt.start();//启动一个绘制线程

// bitmap = Bitmap.createBitmap(ivDraw.getWidth(),ivDraw.getHeight(), Bitmap.Config.ARGB_8888);
// canvas=new Canvas(bitmap);
// ivDraw.setImageBitmap(bitmap);
//
// P = new Paint();
// int c = Color.rgb(0,255,0);
// P.setColor©;
//
// canvas.drawCircle(0,0,60,P);
// ivDraw.invalidate();
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值