您的位置:首页 > 移动开发 > Android开发

Android_Handler的使用,巨细,慎入

2016-05-31 10:15 447 查看
Handler是啥子,简而言之就是一个用来更新UI的一套机制,和消息处理的机制;

在看代码前,来捋一捋思路。

一般而言,我们常用的Handler的方法主要就有,post,postDelayed,sendMessage,sendMessageDelayed;

现在在来看看Handler与Looper和MessageQueue之间的关系:

Handler:封装了消息的发送,主要包括了消息发送给谁了

Looper:他的内部包含一个消息队列的的,也就是MessageQueue,也就是,所有的Handler发送的消息都是走向这个消息队列的(sendMessage,这就是证明呀)

他有个重要的方法Looper.Loop:他呢就是一个死循环,不断的从MessageQueue拿消息,如果有消息,那就执行,如果没有消息,那就阻塞、

MessageQueue,根据前面说的,这就是一个消息队列,可以添加消息,并且处理消息。

工作过程:Handler内部会和Looper进行关联,也就是说Handler的内部可以找到Looper ,找到了Looper,也就找到了MessageQueue

,在Handler中发送消息,其实就是想MessageQueue队列中发送消息。

简而言之,Handler负责传送消息,Looper接收Handler传来的消息,MessageQueue就是一堆消息的集合(存储容器)

思路BB完了,现在来看看代码吧

post方法的:

publicclassMainActivityextendsActivity
{
      privateTextViewtextView;
      privateHandlerhandler =newHandler();;
      @Override
      protectedvoidonCreate(Bundle
savedInstanceState) {
            super.onCreate(savedInstanceState);
             setContentView(R.layout.activity_main);
            textView=
(TextView) findViewById(R.id.TextView1);
            newThread()
{
                  @Override
                  publicvoidrun()
{
                        try{
                              Thread.sleep(1000);
                        
                              handler.post(newRunnable()
{
                                    @Override
                                    publicvoidrun()
{
                                          //这就是更新UI状态,如果不用Handler,那么程序会认为在子线程内部更改UI,程序直接崩溃
                                          textView.setText("Loing
for a jab!");
                                    }
                              });
                        }catch(InterruptedException
e) {
                              //TODOAuto-generated
catch block
                              e.printStackTrace();
                        }
                  }
            }.start();
      }
}

postDelayed:

publicclassMainActivityextendsActivity
{
      privateTextViewtextView;
      privateHandlerhandler =newHandler();
      privateImageViewimageView;
      privateintimages[]={R.drawable.tupian1,R.drawable.tupian2,R.drawable.tupian3};
      privateMyRunablemyRunable=newMyRunable();
      //指定图片在哪个当前位子
      privateintindex=0;
      classMyRunableimplementsRunnable{
            @Override
            publicvoidrun()
{
                  index++;
                  index=index%3;
                  imageView.setImageResource(images[index]);
                  handler.postDelayed(myRunable,
1000);//传入的对象,和延期的时间
                  System.out.println("线程内");
            }
      }
      @Override
      protectedvoidonCreate(Bundle
savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            textView=
(TextView) findViewById(R.id.TextView1);
            imageView=
(ImageView) findViewById(R.id.imageView1);
            handler.postDelayed(myRunable,
1000);
            System.out.println("线程外");
      }
}

sendMessage:

以下是Handler进行int型数据传送的方法

首先就是实例化Handler方法的时候,重写handMessage方法,textView.setText(""+msg.arg1)把要传入的内容显示到text上面

privateHandlerhandler =newHandler(){
            publicvoidhandleMessage(android.os.Message
msg) {
                  textView.setText(""+msg.arg1);
            };
      };

然后就是调用这个方法,传送数据

      newThread(){
                  @Override
                  publicvoidrun()
{
                        try{
                              Thread.sleep(1000);
                              Message message=newMessage();
                              message.arg1=88;
                              handler.sendMessage(message);
                        }catch(InterruptedException
e) { 
                              e.printStackTrace();
                        }
                  }

            }.start();

以下是进行对象数据的传送

实例化

    private Handler handler=new Handler(new Handler.Callback() {

    @Override
    public boolean handleMessage(Message msg) {

        textView.setText(""+msg.obj);

        Toast.makeText(getApplicationContext(),""+1,1).show();

        return false;
//       retunrn true;则下面的的handleMessage就不会进行了
    }

}){

    @Override
    public void handleMessage(Message msg) {

        Toast.makeText(getApplicationContext(),""+2,1).show();

    }

};

具体函数

new Thread(){

    @Override
    public void run() {

        try {

            Thread.sleep(1000);

            Message message=handler.obtainMessage();

            User user=new User();

            user.age=10;

            user.name="HAHA";

            message.obj=user;

            message.sendToTarget();

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    }

}.start();

方法扯完了,再来扯点有内涵的,

自定义与线程相关的Handle这个怎么样:

package com.example.administrator.android_handler;

import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

import android.os.Looper;

import android.os.Message;

import android.util.Log;

import android.widget.TextView;

public class SeconActivity extends Activity {

    private Handler mhandler = new Handler(){

        @Override

        public void handleMessage(Message msg) {

            Log.d("test","我是主线程:"+Thread.currentThread());

        }

    };

    class MyThread extends Thread{

        public Handler handler;

        @Override

        public void run() {

            //创建一个Looper

            Looper.prepare();

            handler=new Handler(){

                @Override

                public void handleMessage(Message msg) {

                    Log.d("test","线程:"+Thread.currentThread()); 

                }

            };

            Looper.loop();

        }

    }

    private MyThread thread;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        // TODO Auto-generated method stub

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        TextView textView=new TextView(this);

        textView.setText("hello handle");

        setContentView(textView);

        thread=new MyThread();

        thread.start();

        try {

            thread.sleep(500);

        } catch (InterruptedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

        thread.handler.sendEmptyMessage(1);

        mhandler.sendEmptyMessage(1);

    }

}

然后即使这个东西HandlerThread:

public class ThreadActivity extends Activity {

    private TextView textView;

    private HandlerThread handlerThread;

    private Handler handler;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        textView=new TextView(this);

        textView.setText("handler Thread");

        setContentView(textView);

        handlerThread=new HandlerThread("hander thread");

        handlerThread.start();

        handler=new Handler(handlerThread.getLooper()){

            @Override

            public void handleMessage(Message msg) {

                Log.d("test","线程:"+Thread.currentThread());

                Log.d("test","handlerThread.getLooper():"+handlerThread.getLooper());

            }

        };

        handler.sendEmptyMessage(1);

    }

}

代码如上,这是正确的写法,可以打印出子线程,好的,如果呢,我们把handler=new Handler(handlerThread.getLooper)改成handler=new
Handler()的话,那么显示的就会使主线程了。因为他这个就是直接UI里面创建的Handler。我们再改改,handler=new Handler(handler.getLooper)如果改成这样的话呢,那就直接报错了,错误是,空指针,为啥呢,因为你一个线程创建的时候,内部会和Looper进行关联,但是,你的这个handler=new
Handler(handler.getLooper),其实就是一个创建的过程,你程序走到这,你Handler还没有Looper进行关联呢,这可不就是一个空指针嘛 。所以这个方法可以防止多线程并发而导致的空指针问题。

主线程和子线程之间的信息交互:

代码如下:

public class FourActivity extends Activity implements View.OnClickListener {

    private Button btSend;

    private Button btStop;

    private HandlerThread thread;

    //这是主线程的创建

    private Handler handler = new Handler() {

        @Override

        public void handleMessage(Message msg) {

            Message message = new Message();

            Log.d("test", "线程:" + Thread.currentThread());

            Log.d("test", "消息内容:" + message);

            threadHandler.sendMessageDelayed(message, 1000);

        }

    };

    private Handler threadHandler;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.four);

        btSend = (Button) findViewById(R.id.bt_send);

        btStop = (Button) findViewById(R.id.bt_stop);

        btSend.setOnClickListener(this);

        btStop.setOnClickListener(this);

        thread = new HandlerThread("handlerThread");

        thread.start();

//子线程的创建

        threadHandler = new Handler(thread.getLooper()) {

            @Override

            public void handleMessage(Message msg) {

                Message message = new Message();

                handler.sendMessageDelayed(message, 1000);

                Log.d("test", "线程:" + Thread.currentThread());

                Log.d("test", "消息内容:" + message);

            }

        };

    }

    @Override

    public void onClick(View v) {

        switch (v.getId()) {

            case R.id.bt_send:

                handler.sendEmptyMessage(1);

                Log.d("test", "send");

                break;

            case R.id.bt_stop:

                    handler.removeMessages(1);

                

                break;

        }

    }

}

还有就是,我发现这个,循环会一直进行下去,没有办法取消,如果各位亲有发现取消的方法,请告之,谢谢了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息