Android 通信机制之handler消息机制详解源码分析与使用

 

目录

 

Handler介绍:

1,什么是handler:

2,为什么使用handler

3,handler有什么用: 

4, 怎么使用handler 

Handler常用方法

1,Handler构造方法:

2,Handler公共方法:

公共方法

Handler 源码理解

1,Handler四大核心对象:

2,原理图:

3,Message类介绍:

4,Handler()构造 (取出looper对象)

5,ActivityThread(存Looper对象)

6,Handler发送消息

7,Handler内部进行取消息 ,并且进行处理

handler使用:

post(Runnable r)在子线程更新UI时使用

sendEmptyMessage发送空标记消息

sendMessage发送标记消息

postDelayed延时更新UI

总结:


Handler介绍:

1,什么是handler:

【1】Android消息机制: handler是更新UI界面的机制,也是消息处理的机制,我们可以发送消息,也可以处理消息
 
【2】Handler允许您发送和处理Message和与线程的MessageQueue...每个Handler实例都与单个线程和该线程的消息队列相关联。
 
【2】当您创建一个新的Handler时,它被绑定到创建它的线程的线程/消息队列--从那时起,它将把消息和运行程序传递到消息队列中,并在它们从消息队列中出来时执行它们。 
 
【3】基本原理的概括:Handler是发送消息Message给Looper,Looper是封装消息的载体,Looper中封装了一个MessageQueue,Looper.loop()是把消息MessageQueue中的消息返还给Handler.
 
 
Android 通信机制之handler消息机制详解源码分析与使用_第1张图片

2,为什么使用handler

【1】问题:ANR :application not response  应用无响应
             Android 通信机制之handler消息机制详解源码分析与使用_第2张图片
  • 当应用程序在主线程(main线程 ui线程)进行耗时(比如连接网络,拷贝大的数据 )的操作 一般5秒钟无响应就会报ANR为了避免出现ANR我们把耗时操作放在子线程去做,但是在子线程去更新UI会报错误
10-06 02:17:57.778: W/System.err(1596): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

 

【2】只有在主线程才能更新UI,我们要开始用Handler了。handler 也可以用于延时操作。
 
 

3,handler有什么用: 

【1】调度消息和运行表,以便在将来的某个时间点执行; 
 
【2】将要在与您自己的线程不同的线程上执行的操作排队。 
 
【3】Handler是android封装好的一套更新UI的机制,也是发送消息,传递消息,处理消息的机制,如果要想更新UI,就必须要遵循这套机制,否则就会抛出异常。
  • 例如我们使用多线程来更新UI时,如果没有加锁的话,会产生界面错乱,但是如果增加了锁,但是性能又会下降,根据一行产生的问题android给我们封装好了一套更新UI的机制,我们只需要遵循这套机制即可。否则我们需要自己写。要处理这些问题。 
 

4, 怎么使用handler 

【1】调度消息使用方法:
  • 调用方法允许您在消息队列接收到可运行对象时对它们进行排队,通过Message对象发送讯息由Handler理的一系列数据。handleMessage(Message)方法(要求您实现Handler的子类)。
 
post(Runnable)
post(Runnable)
 sendMessage(Message)
sendMessageAtTime(Message, long)
postAtTime(java.lang.Runnable, long)
postDelayed(Runnable, Object, long)
sendEmptyMessage(int)
sendMessageDelayed(Message, long)
【2】对象将当投递或发送到Handler时,您可以允许在消息队列准备就绪时立即处理该项,或者在消息队列被处理之前指定一个延迟,或者指定处理它的绝对时间。后两者允许您实现超时、滴答和其他基于时间的行为。 
 
【3】当为应用程序创建进程时,其主线程专用于运行消息队列,负责管理顶级应用程序对象(活动、广播接收器等)及其创建的任何窗口。您可以创建自己的线程,并通过Handler与主应用程序线程进行通信。这是通过调用相同的岗或发送讯息方法,但来自您的新线程。然后在Handler的消息队列中对给定的可运行或消息进行调度,并在适当时进行处理。



Handler常用方法

 

1,Handler构造方法:

Handler()

 

默认构造函数将此处理程序与Looper用于当前线程。

Handler(Handler.Callback callback)

 

构造函数将此处理程序与Looper对于当前线程,并接受一个回调接口,您可以在其中处理消息。

Handler(Looper looper)

 

使用所提供的Looper而不是默认的。

Handler(Looper looper, Handler.Callback callback)

 

使用所提供的Looper而不是默认的,而是接受一个回调接口来处理消息。

2,Handler公共方法:

公共方法

 

 

static Handler

createAsync(Looper looper, Handler.Callback callback)

 

创建一个新的Handler,其发布的消息和运行程序不受同步障碍(如显示vsync)的限制。

static Handler

createAsync(Looper looper)

 

创建一个新的Handler,其发布的消息和运行程序不受同步障碍(如显示vsync)的限制。

void

dispatchMessage(Message msg)

在这里处理系统消息。

final void

dump(Printer pw, String prefix)

 

final Looper

getLooper()

 

String

getMessageName(Message message)

 

返回表示指定消息的名称的字符串。

void

handleMessage(Message msg)

 

子类必须实现这一点才能接收消息。

final boolean

hasCallbacks(Runnable r)

 

检查消息队列中是否有带有回调r的挂起的消息。

final boolean

hasMessages(int what)

 

检查消息队列中是否有代码“什么”的挂起的消息。

final boolean

hasMessages(int what, Object object)

 

检查消息队列中是否有代码“什么”和其obj是“Object”的挂起的消息。

final Message

obtainMessage(int what, Object obj)

 

同obtainMessage(),只是它还设置了返回消息的内容和obj成员。

final Message

obtainMessage()

 

返回一个新的Message来自全局消息池。

final Message

obtainMessage(int what, int arg1, int arg2)

 

同obtainMessage(),只是它还设置了返回消息的内容、arg 1和arg 2成员。

final Message

obtainMessage(int what, int arg1, int arg2, Object obj)

 

同obtainMessage(),只是它还在返回的消息上设置了什么值、obj值、arg 1值和arg 2值。

final Message

obtainMessage(int what)

 

同obtainMessage(),除非它还设置返回消息的哪个成员。

final boolean

post(Runnable r)

 

导致将Runnable r添加到消息队列中。

final boolean

postAtFrontOfQueue(Runnable r)

 

向实现Runnable的对象发布消息。

final boolean

postAtTime(Runnable r, long uptimeMillis)

 

使Runnable r添加到消息队列,并在uptimeMillis.

final boolean

postAtTime(Runnable r, Object token, long uptimeMillis)

 

使Runnable r添加到消息队列,并在uptimeMillis.

final boolean

postDelayed(Runnable r, long delayMillis)

 

使Runnable r被添加到消息队列,并在指定的时间流逝后运行。

final boolean

postDelayed(Runnable r, Object token, long delayMillis)

 

使Runnable r被添加到消息队列,并在指定的时间流逝后运行。

final void

removeCallbacks(Runnable r)

 

删除消息队列中所有可运行r的挂起的帖子。

final void

removeCallbacks(Runnable r, Object token)

 

删除所有可运行的挂起的帖子r有对象令牌在消息队列中。

final void

removeCallbacksAndMessages(Object token)

 

删除所有挂起的回调文章,并发送以下消息OBJ是令牌.

final void

removeMessages(int what)

 

删除消息队列中任何带有代码“什么”的挂起的消息。

final void

removeMessages(int what, Object object)

 

删除任何挂起的消息,其代码为“什么”,其obj是消息队列中的“对象”。

final boolean

sendEmptyMessage(int what)

 

发送只包含哪些值的消息。

final boolean

sendEmptyMessageAtTime(int what, long uptimeMillis)

 

发送只包含要在特定时间传递的值的消息。

final boolean

sendEmptyMessageDelayed(int what, long delayMillis)

 

发送一条消息,该消息只包含要在指定的时间间隔后传递的值。

final boolean

sendMessage(Message msg)

 

将消息推送到消息队列的末尾,在当前时间之前完成所有挂起的消息。

final boolean

sendMessageAtFrontOfQueue(Message msg)

 

将消息队列放在消息队列的前面,在消息循环的下一次迭代中进行处理。

boolean

sendMessageAtTime(Message msg, long uptimeMillis)

在所有挂起的消息在绝对时间之前(以毫秒为单位)之前,将消息放入消息队列中。uptimeMillis.

final boolean

sendMessageDelayed(Message msg, long delayMillis)

 

在所有挂起的消息之前(当前时间+delayMillis)之后,将消息放入消息队列中。

String

toString()

返回对象的字符串表示形式。

Handler 源码理解

1,Handler四大核心对象:

【1】核心类

Message: 消息(数据载体).

Looper: 轮询器. 去MessageQueue取消息 分发给Handler处理

MessageQueue: 消息队列(存储消息). 

Handler: 消息处理器. 发送消息 处理消息   

【2】对应关系

  • handler和Looper的关系是多对一的,在主线程new Handler多个但是 都是通过ActivityThread 主线程中获取的一个Looper对象进行处理*

  • looper和MessageQueue消息队列的关系是一一对应的关系

2,原理图:

【1】解析图:
 

Android 通信机制之handler消息机制详解源码分析与使用_第3张图片

【2】流程图:

Android 通信机制之handler消息机制详解源码分析与使用_第4张图片

3,Message类介绍:

 

【1】什么是Message?

  • Message是封装了需要传递的数据交由Handler 处理的对象。

  • 在android的消息机制中,Message其充当着信息载体的一个角色,通俗的来说,我们看作消息机制就是个工厂的流水线,message就是流水线上的产品,messageQueue就是流水线的传送带。

  • Android的消息机制都通过message这个载体进行传递消息。

【2】Message的作用:

  • 用于存放传递的数据;

  • 是主线程和子线程传递数据的载体

 
【3】如何使用Message:
初始化Message对象
​
Message message= new Message();
Message message= Message.obtain();
Messager message= handler.obtaionMessager();

​

向Message中添加数据:

Message message = Message.obtain();
//TODO 将传递数据,封装到Message消息对象中
message.what = 0;
message.arg1 = 1;
message.arg2 = 2;
message.obj = “传递的内容”;
Bundle bundle = new Bundle();
bundle.putString("name","张三");
message.setData(bundle);

获取Message中存储的数据

private Handler handler = new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int flag1 = msg.what;
            int flag2 = msg.arg1;
            int flag3 = msg.arg2;
            String resultMsg = (String) msg.obj;
            Bundle bundle = msg.getData();
            String name = bundle.getString("name");
        }
    };
【4】介绍一下message 的创建
Message创建消息的方法:
 
Handler.obtain() 底层调用的是Message.obtain()
Message.obtain() 从池子取对象,单向链表 next复用Message,如果没有会new Message()
new Message()

【5】Message.obtain() 可以复用消息  , 单向链表

  • 是从池子里面去取的
  • 如果有消息就直接从spool 里面去取
  • 如果没有就new Message  
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {
    synchronized (sPoolSync) {
        if (sPool != null) {
            Message m = sPool;
            sPool = m.next;
            m.next = null;
            m.flags = 0; // clear in-use flag
            sPoolSize--;
            return m;
        }
    }
    return new Message();
}

4,Handler()构造 (取出looper对象)

hanlder()构造方法,取出looper对象

public Handler(Callback callback, boolean async) {
    //这里是异常判断
    if (FIND_POTENTIAL_LEAKS) {
        final Class klass = getClass();
        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                (klass.getModifiers() & Modifier.STATIC) == 0) {
            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                klass.getCanonicalName());
        }
    }

    //给looper变量赋值
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread " + Thread.currentThread()
                    + " that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}
【1】Handler()构造创建Looper,然后把消息发送到消息队列
  • Handler() 构造中通过Looper.myLooper();  获取mLooper对象并且给mQueue进行赋值
  • handler和Looper的关系是多对一的,在主线程new Handler多个但是 都是通过ActivityThread 主线程中获取的一个Looper对象进行处理
      
  public Handler() {
       
        // 给looper变量赋值
        mLooper = Looper.myLooper();         
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        // 当looper被调用后,获取mLooper对象给mQueue消息队列赋值,
        mQueue = mLooper.mQueue;
        mCallback = null;
        }
【2】myLooper,从当前线程取Looper对象,(取Looper对象)
  • sThreadLocal 是为了处理多线程并发。 
public static final Looper myLooper() {
                // 从当前线程取Looper对象,你在子线程中开启handler会报错,因为子线程中,没有把线程存放进去
        return (Looper)sThreadLocal.get();           //多线程中确认线程唯一的对象, sThreadLocal.get() 就是从线程池中取一个唯一对象
    }

5,ActivityThread(存Looper对象)

【1】ActivityThread 中的main 方法--prepareMainLooper方法下--- prepare(); 在 prepare();中进行对looper的存储
  • ActivityThread往主线程设置Looper对象(存Looper对象)
       
 public static final void main(String[] args) {
                // 往主线程设置Looper对象
        Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        //主线程进入死循环
        Looper.loop();
  
  • prepareMainLooper
  • Looper.prepareMainLooper() , 往当前线程设置Looper对象这样sThreadocal 就可以获取当前线程中的Looper对象
  public static final void prepareMainLooper() {
        prepare();
        setMainLooper(myLooper());
        if (Process.supportsProcesses()) {
            myLooper().mQueue.mQuitAllowed = false;
        }
    }

 

  •   prepare();
public static final void prepare( ) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
       // 往当前线程设置Looper对象
        sThreadLocal.set(new Looper());
    }

 

 
 
【2】Looper类
  • Looper的构造方法,创建消息队列。  looper和MessageQueue消息队列的关系是一一对应的关系
   private Looper() {
                // 创建消息队列
        mQueue = new MessageQueue();
        mRun = true;
        mThread = Thread.currentThread();
    }

6,Handler发送消息

  • handler.sendMessage()发送消息
【1】Handler 发送消息。发送消息内部调用方法最终都会走在sendMessageAtTime,把消息传输给消息队列
handler.sendMessage()
sendMessageDelayed(Message msg, long delayMillis)
sendEmptyMessageAtTime(int what, long uptimeMillis)
sendEmptyMessageDelayed(int what, long delayMillis)
sendEmptyMessage(int what)

 

  • sendMessageAtTime把消息传递给消息队列
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
    {
        boolean sent = false;
        MessageQueue queue = mQueue;
        if (queue != null) {
            msg.target = this;
                        // 把消息传递给消息队列
            sent = queue.enqueueMessage(msg, uptimeMillis);
        }
        else {
            RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
        }
        return sent;
    }

 

【2】queue.enqueueMessage方法消息进行排队
  • queue.enqueueMessage,根据时间对消息进行排队。
  • 当前发送的消息需要马上处理,排到队列头 进行唤醒。
final boolean enqueueMessage(Message msg, long when) {
        if (msg.when != 0) {
            throw new AndroidRuntimeException(msg
                    + " This message is already in use.");
        }
        if (msg.target == null && !mQuitAllowed) {
            throw new RuntimeException("Main thread not allowed to quit");
        }
        final boolean needWake;
        synchronized (this) {
            if (mQuiting) {
                RuntimeException e = new RuntimeException(
                    msg.target + " sending message to a Handler on a dead thread");
                Log.w("MessageQueue", e.getMessage(), e);
                return false;
            } else if (msg.target == null) {
                mQuiting = true;
            }


            msg.when = when;
            //Log.d("MessageQueue", "Enqueing: " + msg);
            Message p = mMessages;
            // 当前发送的消息需要马上处理,排到队列头
            if (p == null || when == 0 || when < p.when) {
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked; // new head, might need to wake up
            } else {
                / 当前发送的消息不需要马上处理,根据时间重新排序
                Message prev = null;
                while (p != null && p.when <= when) {
                    prev = p;
                    p = p.next;
                }
                msg.next = prev.next;
                prev.next = msg;
                needWake = false; // still waiting on head, no need to wake up
            }
        }
        // 根据是否需要唤醒,处理消息
        if (needWake) {
            nativeWake(mPtr);
        }
        return true;
    }

7,Handler内部进行取消息 ,并且进行处理

【1】消息放进消息队列
  • Looper.loop()。ActivityThread 设置Looper的时候调用的loop  主线程进行死循环,(了解消息唤醒机制)
  • ActivityThread 底层中的handler不断去取消息。我们发过来的消息,比如handler 广播,触摸事件 activity的创建。都是通过唤醒去处理的
  • 基于窗口的应用一般内部都有一个死循环
【2】ActivityThread的main方法中调用了 Looper.loop(); 进入了死循环
  public static final void main(String[] args) {
                // 往主线程设置Looper对象
        Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        //主线程进入死循环
        Looper.loop();
  }

 

 
【3】Looper.loop()对消息队列进行获取
  • Looper.loop()。ActivityThread 设置Looper的时候调用的loop  主线程进行死循环,(了解消息唤醒机制)
   
     public static final void loop() {
        Looper me = myLooper();
        
        // 主线程进入死循环
        while (true) {
        }
    }
  • 获取消息,如果有需要执行的消息就调用dispatchMessage进行处理
public static final void loop() {
        Looper me = myLooper();
        MessageQueue queue = me.mQueue;
        
        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        
        while (true) {
             // 从消息队列取消息,如果没有消息就阻塞
            Message msg = queue.next(); // might block
            //if (!me.mRun) {
            //    break;
            //}
            if (msg != null) {
                if (msg.target == null) {
                    // No target is a magic identifier for the quit message.
                    return;
                }
                if (me.mLogging!= null) me.mLogging.println(
                        ">>>>> Dispatching to " + msg.target + " "
                        + msg.callback + ": " + msg.what
                        );
                // 处理消息 target指发送此消息的handler
                msg.target.dispatchMessage(msg);
                if (me.mLogging!= null) me.mLogging.println(
                        "<<<<< Finished to    " + msg.target + " "
                        + msg.callback);
                
                // Make sure that during the course of dispatching the
                // identity of the thread wasn't corrupted.
                final long newIdent = Binder.clearCallingIdentity();
                if (ident != newIdent) {
                    Log.wtf("Looper", "Thread identity changed from 0x"
                            + Long.toHexString(ident) + " to 0x"
                            + Long.toHexString(newIdent) + " while dispatching to "
                            + msg.target.getClass().getName() + " "
                            + msg.callback + " what=" + msg.what);
                }
                
                msg.recycle();
            }
        }
    }

 

  • 处理消息msg.target.dispatchMessage(msg)    返回给handler ,handler 重写handlerMessage方法进行对应操作
  
      public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

handler使用:

post(Runnable r)在子线程更新UI时使用

1, Handler.post( Runnable r)
  • 在子线程更新UI时使用。
 
2,实现原理:
【1】在主线程中new 一个对象Handler handler = newHandler()(会自动绑定到主线程)。
【2】在需要更新子线程里面的地方使用handler.post(runnable);发送一个runnable对象在runnable的run方法中执行我们想要的操作
 
 
 
public class TestActivity extends AppCompatActivity {
    private Handler mHandler = new Handler();    
    private ImageView mImageView;    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        mImageView = (ImageView) findViewById(R.id.image);       
       
        new Thread(new Runnable() {            
            @Override
            public void run() {                
                try {
                    Thread.sleep(2000);
                    mHandler.post(new Runnable() {                        
                        @Override
                        public void run() {
                               mImageView.setImageResource(R.mipmap.ic_launcher);
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

sendEmptyMessage发送空标记消息

1, mHandler.sendEmptyMessage(0x123);
  • 在子线程中发送一个带标记的空消息,给主线程。
  • 在handler中可以通过Message  .what判断消息类型,并且进行处理
 
 
2,实现原理:
【1】在主线程new 一个handler 
【2】在需要更新的地方使用 handler.sendMessage()方法传递一个Message对象。可以使用message对象的arg1参数或者obj参数或者what参数携带参数。
【3】在handler中的回调handler.handleMessage方法中执行想做的方法。
 
public class TestActivity extends AppCompatActivity {
    private ImageView mImageView;    
    private Handler mHandler = new Handler() {        
        @Override
        public void handleMessage(Message msg) {            
                if(msg.what == 0x123) {
                mImageView.setImageResource(R.mipmap.ic_launcher);
            }            
        super.handleMessage(msg);
        }
    };    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        mImageView = (ImageView) findViewById(R.id.image);        
            new Thread(new Runnable() {            
            @Override
            public void run() {                
                try {
                    Thread.sleep(2000);
                    mHandler.sendEmptyMessage(0x123);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

sendMessage发送标记消息

1,  handler.sendMessage(msg);

  • 创建Handler对象,重写handleMessage 方法

  • 开启子线程,通过Message.obtaion方法获取到Message对象

  • 给Message对象添加内容,和标记, handler.sendMessage(msg);在子线程发送消息 

  • 在handler对象中的HandleMessage方法里,获取到对应的what进行处理消息

 

2,实现原理:

【1】开启子线程处理耗时操作,使用handler传输数据:

// 实现按钮点击事件

    public void click(View v) {

        

        //创建一个子线程

        new Thread() {

            public void run() {

                try {

                    if(xxxx){

                        // 把耗时的操作放到子线程里面 bitmap 是要传输的数据

                        Bitmap bitmap = BitmapFactory.decodeStream(in);

                        // 获取message对象,不去 new Message() 使用obtain方法是为了避免创建过多的对象

                        Message msg = Message.obtain();

                        // 数据塞进msg里面

                        msg.obj = bitmap;

                        // 给msg 加一个标识在handler 可以分类进行逻辑处理

                        msg.what = REQUESTSUCESS;

                        handler.sendMessage(msg);

                    }else {

                        Message msg = Message.obtain();

                        msg.what = REQUESTFAIL;

                        handler.sendMessage(msg);

                    }

                } catch (Exception e) {

                    e.printStackTrace();

                    Message msg = Message.obtain();

                    msg.what = REQUESTEXCEPTION;

                    handler.sendMessage(msg);

                }

            }

        }.start();

        

        

【2】创建handler成员变量,接收数据进行UI操作:

    protected static final int REQUESTSUCESS = 0;  

    protected static final int REQUESTFAIL = 1;

    protected static final int REQUESTEXCEPTION= 2;

    //定义一个handler

    private Handler handler = new Handler(){

        //在这个方法里面处理消息

        public void handleMessage(android.os.Message msg) {

            

            switch (msg.what) {

            case REQUESTSUCESS:

                //[1]获取我们携带的数据

                Bitmap bitmap = (Bitmap) msg.obj;

                //[2]把btimap展示到imagview上

                iv.setImageBitmap(bitmap);

                break;



            case REQUESTFAIL:

                iv.setImageBitmap(null);

                Toast.makeText(getApplicationContext(), "图片不存在", 1).show();

                break;

            case REQUESTEXCEPTION:

                iv.setImageBitmap(null);

                Toast.makeText(getApplicationContext(), "图服务器忙", 1).show();

                break;

            }

        };

    };

postDelayed延时更新UI

1,handler.postDelayed(Runnable r, int  i)

  • 发送一个消息,在int i 设置多少之后进行执行

 

2,实现效果

【1】hanlder设置一个延时任务:

参1 任务 参2延时时间

    new Handler().postDelayed(new Runnable() {



            @Override

            public void run() {

              需要实现的逻辑

            }

        }, 2000);



总结:

handler 是android 中处理消息,用于更新UI,我们可以用来实现广告条的轮播,延时任务执行,更新UI,处理数据,和发送数据的使用。

全篇分析介绍了handler,分析handler的源码,还有handler常规的使用方法,希望可以帮助到各位。请点赞支持,相互交流。回谢

 

你可能感兴趣的:(Android,资料库)