How do I fix the deprecation warning in this code? Alternatively, are there any other options for doing this?
Handler().postDelayed({
context?.let {
//code
}
}, 3000)
Use Executor instead of handler for more info Executor.
To achieve post delay use ScheduledExecutorService:
ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = () -> {
public void run() {
// Do something
}
};
worker.schedule(runnable, 2000, TimeUnit.MILLISECONDS);
Consider using coroutines
scope.launch {
delay(3000L)
// do stuff
}
The deprecated function is that constructor for Handler. Use Handler(Looper.myLooper()) .postDelayed(runnable, delay) instead
According to the document (https://developer.android.com/reference/android/os/Handler#Handler()):
Implicitly choosing a Looper during Handler construction can lead to bugs where operations are silently lost (if the Handler is not expecting new tasks and quits), crashes (if a handler is sometimes created on a thread without a Looper active), or race conditions, where the thread a handler is associated with is not what the author anticipated. Instead, use an Executor or specify the Looper explicitly, using Looper#getMainLooper, {link android.view.View#getHandler}, or similar. If the implicit thread local behavior is required for compatibility, use new Handler(Looper.myLooper()) to make it clear to readers.
We should stop using the constructor without a Looper, and specify a Looper instead.
If you want to avoid the null check thing in Kotlin (? or !!) you can use Looper.getMainLooper() if your Handler is working with some UI related thing, like this:
Handler(Looper.getMainLooper()).postDelayed({
Toast.makeText(this@MainActivity, "LOOPER", Toast.LENGTH_SHORT).show()
}, 3000)
Note: use requireContext() instead of this@MainActivity if you are using fragment.
use this
Looper.myLooper()?.let {
Handler(it).postDelayed({
//Your Code
},2500)
}
The handler() etc code is generated by the Android Studio 4.0.1 when a Fullscreen Activity, for example, is created from scratch. I know that we are being encouraged to use Kotlin, which I do, but from time to time I use sample projects to get an idea going. It seems strange that we are chastised by AS when AS actually generates the code. It might be a useful academic activity to go through the errors and fix them but maybe AS could generate new clean code for us enthusiasts...
Only the parameterless constructor is deprecated, it is now preferred that you specify the Looper in the constructor via the Looper.getMainLooper() method.
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
// Your Code
}
}, 3000);
Handler(Looper.getMainLooper()).postDelayed({
// Your Code
}, 3000)
Provide a looper in the Handler Constructor
Handler(Looper.getMainLooper())
Using lifecycle scope this is more easy. Inside activity or fragment.
lifecycleScope.launch {
delay(2000)
// Do your stuff
}
or use handler
Handler(Looper.myLooper()!!)
Java Answer
I wrote a method to use easily. You can use this method directly in your project. delayTimeMillis can be 2000, it means that this code will run after 2 seconds.
private void runJobWithDelay(int delayTimeMillis){
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
//todo: you can call your method what you want.
}
}, delayTimeMillis);
}
I usually use this one
Code:
Handler(Looper.myLooper() ?: return).postDelayed({
// Code what do you want
}, 3000)
Screenshot:
Coroutines Kotlin
private val SPLASH_SCREEN_TIME_OUT_CONST: Long = 3000
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
)
GlobalScope.launch {
delay(SPLASH_SCREEN_TIME_OUT_CONST)
goToIntro()
}
}
private fun goToIntro(){
startActivity(Intent(this, IntroActivity::class.java))
finish()
}
If you are using Variable for Handler and Runnable then use it like this.
private Handler handler;
private Runnable runnable;
handler = new Handler(Looper.getMainLooper());
handler.postDelayed(runnable = () -> {
// Do delayed stuff here
handler.postDelayed(runnable, 1000);
}, delay);
Also You need to remove callbacks in onDestroy()
@Override
public void onDestroy() {
super.onDestroy();
if (handler != null) {
handler.removeCallbacks(runnable);
}
}
It's a good idea use this structure in Kotlin
companion object Run {
fun after(delay: Long, process: () -> Unit) {
Handler(Looper.getMainLooper()).postDelayed({
process()
}, delay)
}
}
Later call as
Run.after(SPLASH_TIME_OUT) {
val action = SplashFragmentDirections.actionSplashFragmentToLogin()
v.findNavController().navigate(action)
}
Handler() and Handler(Handler.Callback callback) constructors are deprecated. Because those can leads to bugs & crashes. Use Executor or Looper explicitly.
For Java
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
//do your work here
}
}, 1000);
I have 3 solutions:
Handler(Looper.getMainLooper()).postDelay({
// code
})
Handler(Looper.myLooper()!!).postDelay({
// code
})
Thread:
Thread({
try{
Thread.sleep(3000)
} catch (e : Exception) {
throw e
}
// code
}).start()
`
import android.os.Looper
import android.os.Handler
inline fun delay(delay: Long, crossinline completion: () -> Unit) {
Handler(Looper.getMainLooper()).postDelayed({
completion()
}, delay)
}
Example:
delay(1000) {
view.refreshButton.visibility = View.GONE
}