码迷,mamicode.com
首页 > 移动开发 > 详细

Android之handler篇

时间:2016-07-20 06:42:41      阅读:271      评论:0      收藏:0      [点我收藏+]

标签:

Android的消息机制主要是指Handler的运行机制,Handler的运行需要底层的MessageQueue和Looper的支撑。对于有开发过Android经验的童鞋都知道,我们一般都是用Handler来更新UI的,更新UI只是handler用法的一部分,下面一起来研究一下handler的神秘面纱。

那么handler是什么?

handler是android给我们用来更新UI的一套机制,也是一套消息处理机制,我们可以通过handler来发送消息,也可以通过它来处理消息

handler主要有以下4种用法

1、sendMessage

2、sendMessageDelayed

3、post(Runnable)

4、postDelayed(Runnable,long)


sendMessage

public class MainActivity extends Activity implements View.OnClickListener {
    private Button btn1;
    private Button btn2;

    private Handler handler = new Handler(){

        //这种方式我们在开发中用的比较多,在主线程中去更新UI
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.v("hjz","执行了handleMessage");
        }
    };

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

        //创建一个回调Callback,并实现handleMessage
        @Override
        public boolean handleMessage(Message msg) {
            Log.v("hjz","执行了Callback里面的handleMessage");
            /**
             * 返回false,说明事件继续向下分发,继续调用下面的handleMessage方法
             * 返回true,说明自己消耗此事件,到此就结束了,起到拦截作用
             * 这种用法似曾相识吧,不错,跟ViewGroup分发事件很类似
             */
            return false;
        }
    }){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.v("hjz","执行了handleMessage");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        setLister();
    }

    private void initView() {
        btn1 = (Button) findViewById(R.id.btn1);
        btn2 = (Button) findViewById(R.id.btn2);
    }

    private void setLister() {
        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn1:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message msg = handler.obtainMessage();
                        msg.what = 1;
                        handler.sendMessage(msg);
                    }
                }).start();
                break;
            case R.id.btn2:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message msg = handler1.obtainMessage();
                        msg.what = 1;
                        handler1.sendMessage(msg);
                    }
                }).start();
                break;
        }
    }
}

xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="handler"/>

    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="handler1"/>
</LinearLayout>
在Callback中handleMessage返回值为false时,点击btn1 和 btn2打印日志:
07-19 21:16:31.091 9943-9943/com.example.handlerdemo V/hjz: 执行了handleMessage
07-19 21:16:34.341 9943-9943/com.example.handlerdemo V/hjz: 执行了Callback里面的handleMessage
07-19 21:16:34.341 9943-9943/com.example.handlerdemo V/hjz: 执行了handleMessage

在Callback中handleMessage返回值为true时,点击btn1 和 btn2打印日志:

07-19 21:23:18.991 22980-22980/com.example.handlerdemo V/hjz: 执行了handleMessage
07-19 21:23:20.901 22980-22980/com.example.handlerdemo V/hjz: 执行了Callback里面的handleMessage
从打印的日志中也验证了在上面handler1的分析


sendMessageDelayed

 case R.id.btn1:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message msg = handler.obtainMessage();
                        msg.what = 1;
                        /**
                         * 第一个参数是一个Message对象
                         * 第二次参数是延迟时间(单位毫秒)
                         */
                        handler.sendMessageDelayed(msg,1000);
                    }
                }).start();
                break;


post(Runnable)

private Handler postHandler = new Handler();
    private void setPost(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                postHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Log.v("hjz","postHandler");
                    }
                });
            }
        }).start();
    }

postDelayed(Runnable,long)

private Handler postDelayedHandler = new Handler();
    private void setPostDelayed(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                postDelayedHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Log.v("hjz","postDelayedHandler");
                    }
                },1000);
            }
        }).start();
    }

上面就是handler的4种基本用法,如果这4种都跟进源码里去看,你会发现它们最终都会去调用sendMessageDelayed(getPostMessage(r), delayMillis)这个方法

接着我们一起分析Handler创建,看一下Handler的构造函数

 public Handler() {
        this(null, false);
    }

public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> 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());
            }
        }

        mLooper = Looper.myLooper();   //获取一个Looper对象,那么Looper在什么时候被创建呢?
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
通过源码ActivityThread中main方法

public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        AndroidKeyStoreProvider.install();

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

  
        Looper.prepareMainLooper();//这句话创建了一个Looper对象,通过Looper构造方法创建一个MessageQueue对象,并将Looper对象存储在ThreadLocal集合中,供后面在Handler创建时获取对应的Looper对象(需注意拿到对应Looper对象也能拿到Looper对应的MessageQueue对象)

        ActivityThread thread = new ActivityThread(); //创建ActivityThread对象
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

一起来看一下上面thread.attach(false)这个方法,源码

private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
            // Watch for getting close to heap limit.
            BinderInternal.addGcWatcher(new Runnable() {
                @Override public void run() {
                    if (!mSomeActivitiesChanged) {
                        return;
                    }
                    Runtime runtime = Runtime.getRuntime();
                    long dalvikMax = runtime.maxMemory();
                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                    if (dalvikUsed > ((3*dalvikMax)/4)) {
                        if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                + " total=" + (runtime.totalMemory()/1024)
                                + " used=" + (dalvikUsed/1024));
                        mSomeActivitiesChanged = false;
                        try {
                            mgr.releaseSomeActivities(mAppThread);
                        } catch (RemoteException e) {
                        }
                    }
                }
            });
        } else {
            // Don't set application object here -- if the system crashes,
            // we can't display an alert, we just want to die die die.
            android.ddm.DdmHandleAppName.setAppName("system_process",
                    UserHandle.myUserId());
            try {
                mInstrumentation = new Instrumentation();
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } catch (Exception e) {
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            }
        }

        // add dropbox logging to libcore
        DropBox.setReporter(new DropBoxReporter());
//重点来看这里
        ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
            @Override
            public void onConfigurationChanged(Configuration newConfig) {
                synchronized (mResourcesManager) {
                    // We need to apply this change to the resources
                    // immediately, because upon returning the view
                    // hierarchy will be informed about it.
                    if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
                        // This actually changed the resources!  Tell
                        // everyone about it.
                        if (mPendingConfiguration == null ||
                                mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                            mPendingConfiguration = newConfig;
//通过一个handler来切换整个activity的生命周期,并实现将handle存储在MessageQueue中
                            sendMessage(H.CONFIGURATION_CHANGED, newConfig); 
                        }
                    }
                }
            }
            @Override
            public void onLowMemory() {
            }
            @Override
            public void onTrimMemory(int level) {
            }
        });
    }

有兴趣的可以自己研究一下ActivityThread中 private class H extends Handler 这个内部类,里面主要实现了activity相关生命周期切换

通过对源码的分析,我们知道Looper创建是在Acitivity开始启动时就创建了

Looper、MessageQueue和Handler的关系

Looper

1、内部包含一个消息队列(MessageQueue),所有的Handler发送消息都走这个消息队列

2、Looper.Looper方法,就是一个死循环,不断从MessageQueue中取消息,如果有消息就处理消息,没有消息就进入阻塞


MessageQueue

MessageQueue就是一个消息队列,可以添加消息,并可以处理消息


Handler

Handler内部跟Looper进行关联,也就是说在Handler的内部可以找到Looper,找到Looper也就可以找到了MessageQueue;在Handler中发送消息,其实就是向MessageQueue队列中发送消息

总结一下三者的关系:handler负责发送消息,Looper负责接收Handler发送过来的消息,并直接把消息回传给handler本身,MessageQueue就是一个存储消息的容器

先写到这里先,后续会继续去完善





Android之handler篇

标签:

原文地址:http://blog.csdn.net/zjws23786/article/details/51946371

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!