Làm thế nào để kiểm tra nếu luồng hiện tại không phải là luồng chính


Câu trả lời:


707
Looper.myLooper() == Looper.getMainLooper()

nếu điều này trả về đúng, thì bạn đang ở trên giao diện người dùng!


Làm thế nào để bạn chạy mã này trong Junit?
John Sardinha

122

bạn có thể sử dụng mã dưới đây để biết chủ đề hiện tại có phải là UI / Chủ đề chính hay không

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

hoặc bạn cũng có thể sử dụng cái này

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

Đây là câu hỏi tương tự


8
Có nên coi cái sau là tùy chọn an toàn hơn vì không có gì đảm bảo rằng bất kỳ luồng tùy ý nào được liên kết với Looper (giả sử rằng luồng chính luôn được liên kết với một kẻ lừa đảo)?
Janus Varmarken

Looper.myLooper()sẽ trả về null nếu luồng không được liên kết với Looper. Vì vậy, cả hai đều an toàn và có cùng kết quả, nhưng cái đầu tiên chậm hơn một chút trong khi nó tìm kiếm bên trong bản đồ để tìm ra kẻ lừa đảo và chủ đề liên quan của nó và làm một số thứ khác.
Saeed Masoumi

59

Cách tốt nhất là cách rõ ràng nhất, mạnh mẽ nhất: *

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

Hoặc, nếu nền tảng thời gian chạy là API cấp 23 (Marshmallow 6.0) trở lên:

Looper.getMainLooper().isCurrentThread()

Xem API Looper . Lưu ý rằng gọi điện Looper.getMainLooper()liên quan đến đồng bộ hóa (xem nguồn ). Bạn có thể muốn tránh chi phí bằng cách lưu trữ giá trị trả về và sử dụng lại nó.

   * tín dụng greg7gkb2cupsOfTech


Bạn có ý nghĩa gì bởi "theo API 23 trở lên"? Điều đó không có ý nghĩa nhiều đối với tôi..Cũng câu trả lời chính xác tương tự đã được đăng bởi AAnkit, bên dưới ..
Mike

@Mike Cảm ơn, tôi đã sửa bit API. AAnkit thực sự ủng hộ Looper.myLooper() == Looper.getMainLooper(), mà tôi nghĩ là ít rõ ràng. Tôi tín dụng greg7gkb.
Michael Allan

1
Đây có nên là một so sánh với == hoặc bằng () vì Android Studio đang đưa ra cảnh báo?
2cupsOfTech

@ 2cupsOfTech Về suy nghĩ thứ 2, đó là lời khuyên tốt. Hiện tại cả hai bài kiểm tra đều giống nhau trong thời gian chạy vì Thread không ghi đè equalsvà do đó rơi trở lại ==, nhưng điều đó có thể thay đổi trong tương lai. Vì vậy, tôi đã sửa câu trả lời.
Michael Allan

25

Tóm tắt các giải pháp, tôi nghĩ đó là giải pháp tốt nhất:

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

Và, nếu bạn muốn chạy một cái gì đó trên luồng UI, bạn có thể sử dụng cái này:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
       //this runs on the UI thread
    }
});

6

Bạn có thể kiểm tra

if(Looper.myLooper() == Looper.getMainLooper()) {
   // You are on mainThread 
}else{
// you are on non-ui thread
}

2

Cho phép tôi mở đầu điều này bằng: Tôi thừa nhận bài đăng này có thẻ 'Android', tuy nhiên, tìm kiếm của tôi không liên quan gì đến 'Android' và đây là kết quả hàng đầu của tôi. Cuối cùng, đối với những người dùng Java SO không phải Android đổ bộ vào đây, đừng quên:

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

Sau khi thiết lập điều này, ở nơi khác trong mã của bạn, bạn có thể dễ dàng kiểm tra xem bạn có thực hiện trên luồng chính bằng:

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

Một chút xấu hổ tôi đã tìm kiếm trước khi nhớ điều này, nhưng hy vọng nó sẽ giúp người khác!


1

bạn có thể xác minh nó trong logcat ddms android trong đó id quá trình sẽ giống nhau nhưng id luồng sẽ khác nhau.


1

Xamarin.Androidcổng: ( C#)

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

Sử dụng:

if (IsMainThread) {
    // you are on UI/Main thread
}

-6

Bạn có thể thử Thread.cienThread (). IsDaemon ()


Tôi không chắc chắn chủ đề UI là một daemon nhưng tôi sẽ tin bạn về điều này. Nhưng làm thế nào bạn sẽ tạo ra sự khác biệt với Chủ đề Daemon mà tôi có thể (nhưng không nên) tạo ra.
AxelH

Tôi đã thử nghiệm trong ứng dụng web của mình, nó cho thấy luồng UI là một luồng Daemon. Tôi đặt một số điểm phá vỡ gỡ lỗi trong môi trường nhật thực và xác minh nó. Chi tiết chủ đề được hiển thị dưới dạng Chủ đề [http-bio-8080-exec-7,5, chính]. Nhấp vào một số trang UI và kiểm tra điểm gỡ lỗi.
Shailendra Singh

Ngoài ra, ngay cả khi trong tên luồng chi tiết, nó hiển thị 'chính' nhưng việc gọi setDaemon (true) trên đối tượng luồng sẽ làm cho nó trở thành daemon.
Shailendra Singh

Bạn đã không đọc phần hay ... Tôi không nghi ngờ (hoàn toàn) về việc nó là một Daemon, tôi đã nói rằng bạn không thể tạo ra sự khác biệt với một chủ đề Daemon khác như thế này.
AxelH

Đặt một cách khác: một chủ đề chính có thể là một chủ đề daemon, nhưng không phải tất cả các chủ đề daemon là chủ đề chính. (Xác định chủ đề chính là những gì đang được hỏi ở đây.)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.