现在 Handler() 已被弃用,我该使用什么?

Har*_*r S 184 java android kotlin android-handler

如何修复此代码中的弃用警告?或者,还有其他选择吗?

Handler().postDelayed({
    context?.let {
        //code
    }
}, 3000)
Run Code Online (Sandbox Code Playgroud)

Nik*_*dva 404

仅不推荐使用无参数构造函数,现在最好Looper通过Looper.getMainLooper()方法在构造函数中指定。

将它用于 Java

new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
    @Override
    public void run() {
        // Your Code
    }
}, 3000);
Run Code Online (Sandbox Code Playgroud)

将其用于 Kotlin

Handler(Looper.getMainLooper()).postDelayed({
    // Your Code
}, 3000)
Run Code Online (Sandbox Code Playgroud)

  • 直接向前... (3认同)
  • getMainLooper()是什么? (3认同)
  • @UNREAL 返回应用程序的主循环程序,它位于应用程序的主线程中。https://developer.android.com/reference/android/os/Looper#getMainLooper() (2认同)

Nic*_*lle 62

如果你想避免在科特林空校验的事(?!!)可以使用Looper.getMainLooper(),如果你Handler正在与一些UI相关的东西,就像这样:

Handler(Looper.getMainLooper()).postDelayed({
   Toast.makeText(this@MainActivity, "LOOPER", Toast.LENGTH_SHORT).show()
}, 3000)
Run Code Online (Sandbox Code Playgroud)

注意:如果您正在使用片段,请使用requireContext()代替this@MainActivity


Nhấ*_*ang 38

从 API 级别 30 开始,不推荐使用 2 个构造函数。

谷歌解释了下面的原因。

在 Handler 构造期间隐式选择 Looper 会导致操作无声地丢失(如果 Handler 不期待新任务并退出)、崩溃(如果有时在没有 Looper 活动的线程上创建处理程序)或竞争条件,处理程序关联的线程不是作者预期的。相反,使用 Executor 或显式指定 Looper,使用 Looper#getMainLooper、{link android.view.View#getHandler} 或类似方法。如果为了兼容性需要隐式线程本地行为,请使用 new Handler(Looper.myLooper(), callback) 向读者说明。

解决方案 1:使用Executor

1.在主线程中执行代码。

爪哇

// Create an executor that executes tasks in the main thread. 
Executor mainExecutor = ContextCompat.getMainExecutor(this);

// Execute a task in the main thread
mainExecutor.execute(new Runnable() {
    @Override
    public void run() {
        // You code logic goes here.
    }
});
Run Code Online (Sandbox Code Playgroud)

科特林

// Create an executor that executes tasks in the main thread.
val mainExecutor = ContextCompat.getMainExecutor(this)

// Execute a task in the main thread
mainExecutor.execute {
    // You code logic goes here.
}
Run Code Online (Sandbox Code Playgroud)

2.在后台线程中执行代码

爪哇

// Create an executor that executes tasks in a background thread.
ScheduledExecutorService backgroundExecutor = Executors.newSingleThreadScheduledExecutor();

// Execute a task in the background thread.
backgroundExecutor.execute(new Runnable() {
    @Override
    public void run() {
        // Your code logic goes here.
    }
});

// Execute a task in the background thread after 3 seconds.
backgroundExecutor.schedule(new Runnable() {
    @Override
    public void run() {
        // Your code logic goes here
    }
}, 3, TimeUnit.SECONDS);
Run Code Online (Sandbox Code Playgroud)

科特林

// Create an executor that executes tasks in a background thread.
val backgroundExecutor: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()

// Execute a task in the background thread.
backgroundExecutor.execute {
    // Your code logic goes here.
}

// Execute a task in the background thread after 3 seconds.
backgroundExecutor.schedule({
    // Your code logic goes here
}, 3, TimeUnit.SECONDS)
Run Code Online (Sandbox Code Playgroud)

注意:使用后记得关闭executor。

backgroundExecutor.shutdown(); // or backgroundExecutor.shutdownNow();
Run Code Online (Sandbox Code Playgroud)

3.在后台线程中执行代码并在主线程上更新UI。

爪哇

// Create an executor that executes tasks in the main thread. 
Executor mainExecutor = ContextCompat.getMainExecutor(this);

// Create an executor that executes tasks in a background thread.
ScheduledExecutorService backgroundExecutor = Executors.newSingleThreadScheduledExecutor();

// Execute a task in the background thread.
backgroundExecutor.execute(new Runnable() {
    @Override
    public void run() {
        // Your code logic goes here.
        
        // Update UI on the main thread
        mainExecutor.execute(new Runnable() {
            @Override
            public void run() {
                // You code logic goes here.
            }
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

科特林

// Create an executor that executes tasks in the main thread. 
val mainExecutor: Executor = ContextCompat.getMainExecutor(this)

// Create an executor that executes tasks in a background thread.
val backgroundExecutor = Executors.newSingleThreadScheduledExecutor()

// Execute a task in the background thread.
backgroundExecutor.execute {
    // Your code logic goes here.

    // Update UI on the main thread
    mainExecutor.execute {
        // You code logic goes here.
    }
}
Run Code Online (Sandbox Code Playgroud)

解决方案 2:使用以下构造函数之一显式指定 Looper。

1.在主线程中执行代码

1.1. 带 Looper 的处理程序

爪哇

Handler mainHandler = new Handler(Looper.getMainLooper());
Run Code Online (Sandbox Code Playgroud)

科特林

val mainHandler = Handler(Looper.getMainLooper())
Run Code Online (Sandbox Code Playgroud)

1.2带有 Looper 和 Handler.Callback 的处理程序

爪哇

Handler mainHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
    @Override
    public boolean handleMessage(@NonNull Message message) {
        // Your code logic goes here.
        return true;
    }
});
Run Code Online (Sandbox Code Playgroud)

科特林

val mainHandler = Handler(Looper.getMainLooper(), Handler.Callback {
    // Your code logic goes here.
    true
})
Run Code Online (Sandbox Code Playgroud)

2.在后台线程中执行代码

2.1. 带 Looper 的处理程序

爪哇

// Create a background thread that has a Looper
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();

// Create a handler to execute tasks in the background thread.
Handler backgroundHandler = new Handler(handlerThread.getLooper()); 
Run Code Online (Sandbox Code Playgroud)

科特林

// Create a background thread that has a Looper
val handlerThread = HandlerThread("HandlerThread")
handlerThread.start()


// Create a handler to execute tasks in the background thread.
val backgroundHandler = Handler(handlerThread.looper)
Run Code Online (Sandbox Code Playgroud)

2.2. 带有 Looper 和 Handler.Callback 的处理程序

爪哇

// Create a background thread that has a Looper
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();

// Create a handler to execute taks in the background thread.
Handler backgroundHandler = new Handler(handlerThread.getLooper(), new Handler.Callback() {
    @Override
    public boolean handleMessage(@NonNull Message message) {
        // Your code logic goes here.
        return true;
    }
});
Run Code Online (Sandbox Code Playgroud)

科特林

// Create a background thread that has a Looper
val handlerThread = HandlerThread("HandlerThread")
handlerThread.start()


// Create a handler to execute taks in the background thread.
val backgroundHandler = Handler(handlerThread.looper, Handler.Callback {
    // Your code logic goes here.
    true
})
Run Code Online (Sandbox Code Playgroud)

注意:使用后记得释放线程。

handlerThread.quit(); // or handlerThread.quitSafely();
Run Code Online (Sandbox Code Playgroud)

3.在后台线程中执行代码并在主线程上更新UI。

爪哇

// Create a handler to execute code in the main thread
Handler mainHandler = new Handler(Looper.getMainLooper());

// Create a background thread that has a Looper
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();

// Create a handler to execute in the background thread
Handler backgroundHandler = new Handler(handlerThread.getLooper(), new Handler.Callback() {
    @Override
    public boolean handleMessage(@NonNull Message message) {
        // Your code logic goes here.
        
        // Update UI on the main thread.
        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                
            }
        });
        
        return true;
    }
});
Run Code Online (Sandbox Code Playgroud)

科特林

// Create a handler to execute code in the main thread
val mainHandler = Handler(Looper.getMainLooper())

// Create a background thread that has a Looper
val handlerThread = HandlerThread("HandlerThread")
handlerThread.start()

// Create a handler to execute in the background thread
val backgroundHandler = Handler(handlerThread.looper, Handler.Callback {
    // Your code logic goes here.

    // Update UI on the main thread.
    mainHandler.post {
        
    }
    true
})
Run Code Online (Sandbox Code Playgroud)

  • 太棒了!干杯 (5认同)

Ngu*_*Son 18

我有3个解决方案

  1. 显式指定 Looper:
    Handler(Looper.getMainLooper()).postDelayed({
        // code
    }, duration)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 指定隐式线程本地行为:
    Handler(Looper.myLooper()!!).postDelayed({
        // code
    }, duration)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用Thread
    Thread({
        try{
            Thread.sleep(3000)
        } catch (e : Exception) {
            throw e
        }
         // code
    }).start()
    
    Run Code Online (Sandbox Code Playgroud)


Gab*_*han 17

不推荐使用的函数是 Handler 的构造函数。使用Handler(Looper.myLooper()) .postDelayed(runnable, delay)替代

  • @EllenSpertus 然后添加空检查,或使用 Looper.myLooper()!如果为空,则会抛出 NPE。如果您位于带有循环程序的线程上,它将返回非空。如果不是,它将返回 null 并应该在任何语言中抛出异常。 (2认同)

Fra*_*esc 15

考虑使用协程

scope.launch {
    delay(3000L)
    // do stuff
}
Run Code Online (Sandbox Code Playgroud)

  • 在“Activity”或“Fragment”内:“lifecycleScope.launch {delay(3000L) }” (8认同)

Din*_*ara 13

Handler()并且Handler(Handler.Callback callback)构造函数已被弃用。因为这些可能会导致错误和崩溃。显式使用 Executor 或 Looper。

对于Java

Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
  @Override
  public void run() {
    //do your work here
   }
}, 1000);
Run Code Online (Sandbox Code Playgroud)


小智 9

使用 Executor 而不是 handler 来获取更多信息Executor
要实现延迟后使用ScheduledExecutorService

ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = () -> {
    public void run() {
        // Do something
    }
};
worker.schedule(runnable, 2000, TimeUnit.MILLISECONDS);
Run Code Online (Sandbox Code Playgroud)


Sha*_*aon 8

使用生命周期范围更容易。内部活动或片段。

 lifecycleScope.launch {
     delay(2000)
     // Do your stuff
 }
Run Code Online (Sandbox Code Playgroud)

或使用处理程序

        Handler(Looper.myLooper()!!)
Run Code Online (Sandbox Code Playgroud)


小智 8

import android.os.Looper
import android.os.Handler

inline fun delay(delay: Long, crossinline completion: () -> Unit) {
    Handler(Looper.getMainLooper()).postDelayed({
        completion()
    }, delay)
}
Run Code Online (Sandbox Code Playgroud)

例子:

delay(1000) {
    view.refreshButton.visibility = View.GONE
}
Run Code Online (Sandbox Code Playgroud)


小智 7

用这个

Looper.myLooper()?.let {
    Handler(it).postDelayed({
        //Your Code
    },2500)
}
Run Code Online (Sandbox Code Playgroud)


Jer*_*olo 7

在处理程序构造函数中提供循环器

Handler(Looper.getMainLooper())
Run Code Online (Sandbox Code Playgroud)