459

I need to check if the thread running a certain piece of code is the main (UI) thread or not. How can I achieve this?

Eiko
  • 25,601
  • 15
  • 56
  • 71
Charlie-Blake
  • 10,832
  • 13
  • 55
  • 90
  • example to demonstrate with thread example http://code2concept.blogspot.in/2015/02/androidhow-to-find-on-which-thread-code.html – Nitesh Tiwari Jun 29 '15 at 18:12

15 Answers15

812
Looper.myLooper() == Looper.getMainLooper()

if this returns true, then you're on the UI thread!

Carnal
  • 21,744
  • 6
  • 60
  • 75
140

you can use below code to know if current thread is UI/Main thread or not

if(Looper.myLooper() == Looper.getMainLooper()) {
   // Current Thread is Main Thread.
}

or you can also use this

if(Looper.getMainLooper().getThread() == Thread.currentThread()) {
   // Current Thread is Main Thread.
}

Here is similar question

Community
  • 1
  • 1
AAnkit
  • 27,299
  • 12
  • 60
  • 71
  • 10
    Should one consider the latter as the safer option as there is no guarantee that any arbitrary thread is associated with a Looper (assuming that the main thread is always associated with a looper)? – Janus Varmarken Jan 07 '16 at 16:58
  • 1
    `Looper.myLooper()` will return null if the thread is not associated with a Looper. So both are safe and have the same result but the first one is a little bit slower while it searches inside a map to find out the looper and its associated thread and do some other stuff . – Saeed Masoumi Nov 03 '18 at 08:26
74

The best way is the clearest, most robust way: *

Thread.currentThread().equals( Looper.getMainLooper().getThread() )

Or, if the runtime platform is API level 23 (Marshmallow 6.0) or higher:

Looper.getMainLooper().isCurrentThread()

See the Looper API. Note that calling Looper.getMainLooper() involves synchronization (see the source). You might want to avoid the overhead by storing the return value and reusing it.

   * credit greg7gkb and 2cupsOfTech

Michael Allan
  • 3,731
  • 23
  • 31
  • What do you mean by "under API 23 or higher"? That doesn't make much sense to me..Also the exact same answer was posted by AAnkit, below.. – Mike Dec 02 '15 at 20:44
  • 1
    @Mike Thanks, I fixed the API bit. AAnkit actually favours `Looper.myLooper() == Looper.getMainLooper()`, which I think is less clear. I credit greg7gkb. – Michael Allan Dec 02 '15 at 21:00
  • 2
    should this be a comparison with == or equals() as Android Studio is raising a warning ? – 2cupsOfTech Jul 28 '17 at 14:19
  • 1
    @2cupsOfTech On 2nd thought, that’s good advice. Currently both tests are the same at runtime because [Thread](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html) does not override `equals`, and so falls back to `==`, but that could change in future. So I corrected the answer. – Michael Allan Oct 09 '18 at 01:10
28

Summarizing the solutions, I think that's the best one:

boolean isUiThread = VERSION.SDK_INT >= VERSION_CODES.M 
    ? Looper.getMainLooper().isCurrentThread()
    : Thread.currentThread() == Looper.getMainLooper().getThread();

And, if you wish to run something on the UI thread, you can use this:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
       //this runs on the UI thread
    }
});
copolii
  • 14,208
  • 10
  • 51
  • 80
android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • Other answers around Handler recommend using ".postDelayed()" rather than ".post()". What is the main difference and can you mention why you recommended using ".post()"? – AJW Nov 10 '21 at 21:26
  • @AJW Sure, here are the docs: https://developer.android.com/reference/android/os/Handler#post(java.lang.Runnable) https://developer.android.com/reference/android/os/Handler#postDelayed(java.lang.Runnable,%20java.lang.Object,%20long) . You use the postDelayed if you wish for the runnable to run at least X ms fro now. – android developer Nov 10 '21 at 23:13
  • Excellent, I appreciate the info. – AJW Nov 10 '21 at 23:15
  • @androiddeveloper How can i run something not in the main thread??? – KJEjava48 Dec 04 '21 at 13:15
  • @KJEjava48 Many ways to do it. The basic one is to create a new `Thread` class and either implement `run` on it or provide a `Runnable` instance to it, and then call `start()` on this `Thread` instance. In Kotlin there is a very short way to do it, using just `thread{ runCodeHere() }` . – android developer Dec 04 '21 at 14:26
7

You can check

if(Looper.myLooper() == Looper.getMainLooper()) {
   // You are on mainThread 
}else{
// you are on non-ui thread
}
Lovekush Vishwakarma
  • 3,035
  • 23
  • 25
4

Allow me to preface this with: I acknowledged this post has the 'Android' tag, however, my search had nothing to do with 'Android' and this was my top result. To that end, for the non-Android SO Java users landing here, don't forget about:

public static void main(String[] args{
    Thread.currentThread().setName("SomeNameIChoose");
    /*...the rest of main...*/
}

After setting this, elsewhere in your code, you can easily check if you're about to execute on the main thread with:

if(Thread.currentThread().getName().equals("SomeNameIChoose"))
{
    //do something on main thread
}

A bit embarrassed I had searched before remembering this, but hopefully it will help someone else!

NekoKikoushi
  • 496
  • 5
  • 16
4

First of all check It is main Thread or not

In Kotlin

fun isRunningOnMainThread(): Boolean {
    return Thread.currentThread() == Looper.getMainLooper().thread
}

In Java

static boolean isRunningOnMainThread() {
  return Thread.currentThread().equals(Looper.getMainLooper().getThread());
}
Kumar Santanu
  • 603
  • 1
  • 7
  • 14
2

just log this line, it should print "main".

Thread.currentThread().name

shubham chouhan
  • 580
  • 7
  • 8
2

In addition to all previous answers

inline fun <T> ensureNotOnMainThread(block: () -> T): T {
    check(Thread.currentThread() != Looper.getMainLooper().thread) { "This function cannot be called on main thread" }
    return block()
}

allows to wrap any method with it, following example :

fun isInDataBase(id: String) = ensureNotOnMainThread { db.contains(id) }
Nicolas Duponchel
  • 1,219
  • 10
  • 17
1

you can verify it in android ddms logcat where process id will be same but thread id will be different.

Vishwanath.M
  • 6,235
  • 11
  • 42
  • 56
1

Xamarin.Android port: (C#)

public bool IsMainThread => Build.VERSION.SdkInt >= BuildVersionCodes.M
    ? Looper.MainLooper.IsCurrentThread
    : Looper.MyLooper() == Looper.MainLooper;

Usage:

if (IsMainThread) {
    // you are on UI/Main thread
}
Mehdi Dehghani
  • 10,970
  • 6
  • 59
  • 64
0

So another answer to join the company, for some extension file in kotlin:

import android.os.Looper.getMainLooper
import java.lang.Thread.currentThread

val Thread.isMain get() = getMainLooper().thread == this

val isThreadMain get() = getMainLooper().thread == currentThread()
Renetik
  • 5,887
  • 1
  • 47
  • 66
-3

A simple Toast message works also as a quick check.

-3

A coroutines-based, Android-agnostic approach:

val onMainThread: Boolean
    get() = Thread.currentThread() === try {
        runBlocking(Dispatchers.Main.immediate) {
            Thread.currentThread()
        }
    } catch (e: IllegalStateException) {
        // No main dispatcher has been registered; not in an Android context?
        null
    }
Stephen Talley
  • 1,130
  • 15
  • 15
-7

You can try Thread.currentThread().isDaemon()

  • I am not sure the UI thread is a daemon but I will believe you on this one. But how will you make the difference with a Daemon Thread that I could (but should not) create. – AxelH Nov 29 '16 at 13:43
  • I tested in my web app, it shows that UI thread is a Daemon thread. I put some debug break points in eclipse environment and verified it. Thread detail shown as Thread[http-bio-8080-exec-7,5,main]. Clicked on some UI pages and checked the debug point. – Shailendra Singh Dec 01 '16 at 07:34
  • Also, even if in the thread name details its showing 'main' but calling setDaemon(true) on thread object will make it daemon. – Shailendra Singh Dec 01 '16 at 07:37
  • You didn't read the good part ... I wasn't doubting (completly) about it being a Daemon, I was telling that you can't make the differences with an other Daemon thread like this. – AxelH Dec 01 '16 at 07:43
  • Put another way: a main thread may be a daemon thread, but not all daemon threads are the main thread. (Identifying the main thread is what is being asked here.) –  May 18 '17 at 16:09
  • Also, it's important to note that the main thread being a daemon is not under programmer control, and an API or VM change could result in this assertion being untrue. –  May 18 '17 at 16:13