栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

为什么UI线程中创建Handler可以不传Looper?

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

为什么UI线程中创建Handler可以不传Looper?

一个APP程序的入口是ActivityThread的main方法,ActivityThread就是我们常说的主线程或UI线程,事实上它并不是一个线程,而是主线程操作的管理者。

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

    Process.setArgV0("");

    //给主线程设置一个Looper实例
    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    //此方法会完成Application对象的初始化,
    //然后调用Application的onCreate()方法
    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");
}

主要方法是Looper.prepareMainLooper(),给主线程设置一个Looper实例

public static void prepareMainLooper() {
    //创建一个Looper实例,将此对象实例存到ThreadLocal的实例中
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        //sMainLooper就是Looper实例,
        //myLooper()方法会从ThreadLocal中获取Looper实例
        sMainLooper = myLooper();
    }
}

Looper类的prepare()方法,创建一个Looper实例,将值存到ThreadLocal的实例中

private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("only one Looper may be created per thread");
    }
    //给ThreadLocal设置一个Looper对象
    sThreadLocal.set(new Looper(quitAllowed));
}

下面是Looper类的myLooper()方法,很简单的

public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

再看Handler的无参构造方法,我们在主线程中就是直接用New Handler()创建其实例

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

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 that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

在其重载构造方法中, mLooper = Looper.myLooper(),从ThreadLocal中获取Looper实例,这就解释了在主线程中构建Handler不需要传Looper的原因,构造方法会自己去获取。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/710995.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号