Handler机制

1,子线程通过sendMessage发消息。mHandler相当于成员变量。

        mHandler.sendMessage(message);

2,主线程通过handleMessage接收到消息,然后更改ui。

其内部实现逻辑如下:

子线程使用handler发消息,主线程在有messQueue消息队列来接收消息,然后循环器Looper不停循环(通过源码我们可以知道looper是一个死循环),将消息传递给主线程handler,进而主线程更改ui。

具体事例代码如下:

package com.example.administrator.myhandler; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.os.Bundle; 
import android.os.Handler;
import android.os.Message;
 import android.support.v7.app.AppCompatActivity; 
import android.widget.ImageView; 
public class MainActivity extends AppCompatActivity { 

private ImageView mImag; 

private Handler mHandler = new Handler(){ 
@Override public void handleMessage(Message msg) { 
//取出消息 Bitmap bitmap = (Bitmap) msg.obj; 
mImag.setImageBitmap(bitmap); 
} 
};

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_main); 
mImag = (ImageView) findViewById(R.id.iv); initData(); 
} 

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

Message message = new Message(); 
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.b); 
message.obj = bitmap; //使用handler从子线程发消息 
mHandler.sendMessage(message); 

} }).start(); 
} 
}

为什么不可以子线程更改ui呢?实际上,Android是这样考虑的:

Android 中主线程也叫 UI 线程,那么从名字上我们也知道主线程主要是用来创建、更新 UI 的,而其他耗时操作,比如网络访问,或者文件处理,多媒体处理等都需要在子线程中操作,之所以在子线程中操作是为了保证 UI 的流畅程度,手机显示的刷新频率是 60Hz,也就是一秒钟刷新 60 次,每 16.67 毫秒刷新一次,为了不丢帧,那么主线程处理代码最好不要超过 16 毫秒。当子线程处理完数据后,为了防止 UI 处理逻辑的混乱,Android 只允许主线程修改 UI,那么这时候就需要 Handler 来充当子线程和主线程之间的桥梁了。

在 Android 中主线程如何给子线程发 Message? 

其实可以把上面的过程逆过来就可以了:在主线程发消息,子线程中new出Handler,接收消息。道理是一样的。

总结
应用启动是从 ActivityThread 的 main 开始的,先是执行了 Looper.prepare(),该方法先是 new 了一个 Looper 对象,在私有的构造方法中又创建了 MessageQueue 作为此 Looper 对象的成员变量,Looper 对象通过 ThreadLocal 绑定 MainThread 中;


当我们创建 Handler 子类对象时,在构造方法中通过 ThreadLocal 获取绑定的 Looper 对象,并获取此 Looper 对象的成员变量 MessageQueue 作为该 Handler 对象的成员变量;
在子线程中调用上一步创建的 Handler 子类对象的 sendMesage(msg) 方法时,在该方法中将 msg 的 target 属性设置为自己本身,同时调用成员变量 MessageQueue 对象的 enqueueMessag() 方法将 msg 放入 MessageQueue 中;


主线程创建好之后,会执行 Looper.loop() 方法,该方法中获取与线程绑定的 Looper 对象,继而获取该 Looper 对象的成员变量 MessageQueue 对象,并开启一个会阻塞(不占用资源)的死循环,只要 MessageQueue 中有 msg,就会获取该 msg,并执行 msg.target.dispatchMessage(msg) 方法(msg.target 即上一步引用的 handler 对象),此方法中调用了我们第二步创建 handler 子类对象时覆写的 handleMessage() 方法。

Handler 的 软引用,避免内存泄漏:

public class MainActivity extends AppCompatActivity {

    private static MyHandler myHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myHandler = new MyHandler(this); 

    }

private class  MyHandler extends Handler{
    private final WeakReference<MainActivity> mActivity;

    private  MyHandler(MainActivity activity){
        mActivity = new WeakReference<MainActivity>(activity);
    }

    @Override
    public void handleMessage(@NonNull Message msg) {
        MainActivity mainActivity = mActivity.get();
        if (mainActivity != null){

        }
    }
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值