Android_Handler的使用,巨细,慎入

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;
        }
    }
}

还有就是,我发现这个,循环会一直进行下去,没有办法取消,如果各位亲有发现取消的方法,请告之,谢谢了


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值