html5中文学习网

您的位置: 首页 > android » 正文

Android中检测当前是否为主线程最可靠的解决方法_Android

[ ] 已经帮助:人解决问题

如果在Android中判断某个线程是否是主线程?对于这个问题,你可能说根据线程的名字,当然这个可以解决问题,但是这样是最可靠的么?万一某天Google一下子将线程的名字改称其他神马东西呢。cQeHTML5中文学习网 - HTML5先行者学习网

方法揭晓cQeHTML5中文学习网 - HTML5先行者学习网

下面的方法是最可靠的解决方案。cQeHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
cQeHTML5中文学习网 - HTML5先行者学习网
public static boolean isInMainThread() {cQeHTML5中文学习网 - HTML5先行者学习网
      return Looper.myLooper() == Looper.getMainLooper();cQeHTML5中文学习网 - HTML5先行者学习网
}cQeHTML5中文学习网 - HTML5先行者学习网
cQeHTML5中文学习网 - HTML5先行者学习网

实际上,写到这里就基本解决了文章标题的问题了,但是仅仅研究到这里太肤浅了,刨的不够深,所以需要继续,希望你也可以继续读下去。cQeHTML5中文学习网 - HTML5先行者学习网

刨根问底cQeHTML5中文学习网 - HTML5先行者学习网

实验一cQeHTML5中文学习网 - HTML5先行者学习网

好,现在,我们对这个稳定的方法做一些测试,首先,下面的方法会增加一些调试打印信息。cQeHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
cQeHTML5中文学习网 - HTML5先行者学习网
private boolean isInMainThread() {cQeHTML5中文学习网 - HTML5先行者学习网
    Looper myLooper = Looper.myLooper();cQeHTML5中文学习网 - HTML5先行者学习网
  Looper mainLooper = Looper.getMainLooper();cQeHTML5中文学习网 - HTML5先行者学习网
  Log.i(LOGTAG, "isInMainThread myLooper=" + myLoopercQeHTML5中文学习网 - HTML5先行者学习网
      + ";mainLooper=" + mainLooper);cQeHTML5中文学习网 - HTML5先行者学习网
  return myLooper == mainLooper;cQeHTML5中文学习网 - HTML5先行者学习网
}cQeHTML5中文学习网 - HTML5先行者学习网
cQeHTML5中文学习网 - HTML5先行者学习网
好,然后我们在主线程中运行一个测试,调用上述方法。比如我们这样调用。cQeHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
cQeHTML5中文学习网 - HTML5先行者学习网
Log.i(LOGTAG, "testInMainThread inMainThread=" + isInMainThread());cQeHTML5中文学习网 - HTML5先行者学习网
cQeHTML5中文学习网 - HTML5先行者学习网

OK,我们看一下输出日志。验证OK。cQeHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
cQeHTML5中文学习网 - HTML5先行者学习网
I/TestInMainThread(32028): isInMainThread myLooper=Looper{40d35ef8};mainLooper=Looper{40d35ef8}cQeHTML5中文学习网 - HTML5先行者学习网
I/TestInMainThread(32028): testInMainThread inMainThread=truecQeHTML5中文学习网 - HTML5先行者学习网
cQeHTML5中文学习网 - HTML5先行者学习网

实验二cQeHTML5中文学习网 - HTML5先行者学习网

现在我们继续在一个没有消息循环的非主线程,进行验证。cQeHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
cQeHTML5中文学习网 - HTML5先行者学习网
new Thread() {cQeHTML5中文学习网 - HTML5先行者学习网
    @OverridecQeHTML5中文学习网 - HTML5先行者学习网
    public void run() {cQeHTML5中文学习网 - HTML5先行者学习网
      Log.i(LOGTAG, "testIn NOT in MainThread isMainThread="cQeHTML5中文学习网 - HTML5先行者学习网
          + isInMainThread());cQeHTML5中文学习网 - HTML5先行者学习网
      super.run();cQeHTML5中文学习网 - HTML5先行者学习网
  }cQeHTML5中文学习网 - HTML5先行者学习网
}.start();cQeHTML5中文学习网 - HTML5先行者学习网
cQeHTML5中文学习网 - HTML5先行者学习网
正如我们看到的如下日志结果,主线程的Looper(翻译成循环泵,不是很好听)已经被初始化赋值。但是我们新创建的线程的looper还是null。这是因为Android中的线程默认没有一个和它绑定了的消息循环(Threads by default do not have a message loop associated with them. Of course, the method works)cQeHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
cQeHTML5中文学习网 - HTML5先行者学习网
I/TestInMainThread(32028): isInMainThread myLooper=null;mainLooper=Looper{40d35ef8}cQeHTML5中文学习网 - HTML5先行者学习网
I/TestInMainThread(32028): testIn NOT in MainThread isMainThread=falsecQeHTML5中文学习网 - HTML5先行者学习网
cQeHTML5中文学习网 - HTML5先行者学习网

实验三cQeHTML5中文学习网 - HTML5先行者学习网

继续,我们创建一个绑定了消息循环的线程,根据Android开发者文档说明,以下是一个典型的创建消息循环线程的示例,使用单独prepare()方法和loop()方法来创建一个绑定到Looper的Handler。cQeHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
cQeHTML5中文学习网 - HTML5先行者学习网
new Thread() {cQeHTML5中文学习网 - HTML5先行者学习网
  private Handler mHandler;cQeHTML5中文学习网 - HTML5先行者学习网
  @OverridecQeHTML5中文学习网 - HTML5先行者学习网
  public void run() {cQeHTML5中文学习网 - HTML5先行者学习网
      Looper.prepare();cQeHTML5中文学习网 - HTML5先行者学习网
      mHandler = new Handler() {cQeHTML5中文学习网 - HTML5先行者学习网
            public void handleMessage(Message msg) {cQeHTML5中文学习网 - HTML5先行者学习网
              // process incoming messages herecQeHTML5中文学习网 - HTML5先行者学习网
          }cQeHTML5中文学习网 - HTML5先行者学习网
      };cQeHTML5中文学习网 - HTML5先行者学习网
      Log.i(LOGTAG, "testInNonMainLooperThread isMainThread="cQeHTML5中文学习网 - HTML5先行者学习网
            + isInMainThread());cQeHTML5中文学习网 - HTML5先行者学习网
      Looper.loop();cQeHTML5中文学习网 - HTML5先行者学习网
  }cQeHTML5中文学习网 - HTML5先行者学习网
      cQeHTML5中文学习网 - HTML5先行者学习网
}.start();cQeHTML5中文学习网 - HTML5先行者学习网
cQeHTML5中文学习网 - HTML5先行者学习网

OK,现在再次检查以下日志,cQeHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
cQeHTML5中文学习网 - HTML5先行者学习网
I/TestInMainThread(32028): isInMainThread myLooper=Looper{40d72c58};mainLooper=Looper{40d35ef8}cQeHTML5中文学习网 - HTML5先行者学习网
I/TestInMainThread(32028): testInNonMainLooperThread isMainThread=falsecQeHTML5中文学习网 - HTML5先行者学习网
cQeHTML5中文学习网 - HTML5先行者学习网

两个Looper都被初始化赋值了,但是他们是不同的对象。cQeHTML5中文学习网 - HTML5先行者学习网

原理发掘cQeHTML5中文学习网 - HTML5先行者学习网

但是,这是为什么呢,这里面有什么奥秘呢? 好,让我们看以下Looper.classcQeHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
cQeHTML5中文学习网 - HTML5先行者学习网
// sThreadLocal.get() will return null unless you've called prepare().cQeHTML5中文学习网 - HTML5先行者学习网
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();cQeHTML5中文学习网 - HTML5先行者学习网
private static Looper sMainLooper;  // guarded by Looper.classcQeHTML5中文学习网 - HTML5先行者学习网

/**cQeHTML5中文学习网 - HTML5先行者学习网
 * Initialize the current thread as a looper, marking it as ancQeHTML5中文学习网 - HTML5先行者学习网
 * application's main looper. The main looper for your applicationcQeHTML5中文学习网 - HTML5先行者学习网
 * is created by the Android environment, so you should never needcQeHTML5中文学习网 - HTML5先行者学习网
 * to call this function yourself.  See also: {@link #prepare()}cQeHTML5中文学习网 - HTML5先行者学习网
 */cQeHTML5中文学习网 - HTML5先行者学习网
public static void prepareMainLooper() {cQeHTML5中文学习网 - HTML5先行者学习网
    prepare(false);cQeHTML5中文学习网 - HTML5先行者学习网
    synchronized (Looper.class) {cQeHTML5中文学习网 - HTML5先行者学习网
        if (sMainLooper != null) {cQeHTML5中文学习网 - HTML5先行者学习网
            throw new IllegalStateException("The main Looper has already been prepared.");cQeHTML5中文学习网 - HTML5先行者学习网
        }cQeHTML5中文学习网 - HTML5先行者学习网
        sMainLooper = myLooper();cQeHTML5中文学习网 - HTML5先行者学习网
    }cQeHTML5中文学习网 - HTML5先行者学习网
}cQeHTML5中文学习网 - HTML5先行者学习网

private static void prepare(boolean quitAllowed) {cQeHTML5中文学习网 - HTML5先行者学习网
    if (sThreadLocal.get() != null) {cQeHTML5中文学习网 - HTML5先行者学习网
        throw new RuntimeException("Only one Looper may be created per thread");cQeHTML5中文学习网 - HTML5先行者学习网
    }cQeHTML5中文学习网 - HTML5先行者学习网
    sThreadLocal.set(new Looper(quitAllowed));cQeHTML5中文学习网 - HTML5先行者学习网
}cQeHTML5中文学习网 - HTML5先行者学习网

/**cQeHTML5中文学习网 - HTML5先行者学习网
 * Return the Looper object associated with the current thread.  cQeHTML5中文学习网 - HTML5先行者学习网
 * Returns null if the calling thread is not associated with a Looper.cQeHTML5中文学习网 - HTML5先行者学习网
 */cQeHTML5中文学习网 - HTML5先行者学习网
public static Looper myLooper() {cQeHTML5中文学习网 - HTML5先行者学习网
    return sThreadLocal.get();cQeHTML5中文学习网 - HTML5先行者学习网
}cQeHTML5中文学习网 - HTML5先行者学习网

 /** Returns the application's main looper, which lives in the main thread of the application.cQeHTML5中文学习网 - HTML5先行者学习网
 */cQeHTML5中文学习网 - HTML5先行者学习网
public static Looper getMainLooper() {cQeHTML5中文学习网 - HTML5先行者学习网
    synchronized (Looper.class) {cQeHTML5中文学习网 - HTML5先行者学习网
        return sMainLooper;cQeHTML5中文学习网 - HTML5先行者学习网
    }cQeHTML5中文学习网 - HTML5先行者学习网
}cQeHTML5中文学习网 - HTML5先行者学习网

cQeHTML5中文学习网 - HTML5先行者学习网

对于主线程来说,prepareMainLooper这个方法会被Android运行环境调用,而不是程序显式调用。通过这个方法,主线程的looper被创建,并且将对象引用传递给sMainLooper。所以保证了主线程myLooper()获取到的引用和getMainLooper()获取到的都是同一个引用。cQeHTML5中文学习网 - HTML5先行者学习网

对于没有消息循环的非主线程,默认的当前线程的looper是null,因为你从来没有手动地调用prepare(),所以它和主线程的looper不一样。cQeHTML5中文学习网 - HTML5先行者学习网

对于绑定了消息循环的非主线程,当调用Looper.prepare方法时,主线程的Looper已经由Android运行环境创建,当调用prepare方法后,绑定到这个非主线程的looper被创建,当然,这不可能和主线程的Looper一样。cQeHTML5中文学习网 - HTML5先行者学习网

综上所述,这个方法是可靠的。cQeHTML5中文学习网 - HTML5先行者学习网

(责任编辑:)
推荐书籍
推荐资讯
关于HTML5先行者 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助