Convert indefinitely running Runnable from java to kotlin - java

I have some code like this in java that monitors a certain file:
private Handler mHandler = new Handler();
private final Runnable monitor = new Runnable() {
public void run() {
// Do my stuff
mHandler.postDelayed(monitor, 1000); // 1 second
}
};
This is my kotlin code:
private val mHandler = Handler()
val monitor: Runnable = Runnable {
// do my stuff
mHandler.postDelayed(whatToDoHere, 1000) // 1 second
}
I dont understand what Runnable I should pass into mHandler.postDelayed. What is the right solution? Another interesting thing is that the kotlin to java convertor freezes when I feed this code.

Lambda-expressions do not have this, but object expressions (anonymous classes) do.
object : Runnable {
override fun run() {
handler.postDelayed(this, 1000)
}
}

A slightly different approach which may be more readable
val timer = Timer()
val monitor = object : TimerTask() {
override fun run() {
// whatever you need to do every second
}
}
timer.schedule(monitor, 1000, 1000)
From: Repeat an action every 2 seconds in java

Lambda-expressions do not have this, but object expressions (anonymous classes) do. Then the corrected code would be:
private val mHandler = Handler()
val monitor: Runnable = object : Runnable{
override fun run() {
//any action
}
//runnable
}
mHandler.postDelayed(monitor, 1000)

runnable display Toast Message "Hello World every 4 seconds
//Inside a class main activity
val handler: Handler = Handler()
val run = object : Runnable {
override fun run() {
val message: String = "Hello World" // your message
handler.postDelayed(this, 4000)// 4 seconds
Toast.makeText(this#MainActivity,message,Toast.LENGTH_SHORT).show() // toast method
}
}
handler.post(run)
}

var handler=Handler()
handler.postDelayed(Runnable { kotlin.run {
// enter code here
} },2000)

Related

Handler deprecated [duplicate]

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)
Only the parameterless constructor is deprecated, it is now preferred that you specify the Looper in the constructor via the Looper.getMainLooper() method.
Use it for Java
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
// Your Code
}
}, 3000);
Use it for Kotlin
Handler(Looper.getMainLooper()).postDelayed({
// Your Code
}, 3000)
Source : developer.android.com
From API level 30, there are 2 constructors are deprecated.
Handler()
Handler(Handler.Callback)
Google explains the reason below.
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(), callback) to make it clear to readers.
Solution 1: Use an Executor
1. Execute code in the main thread.
Java
// 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.
}
});
Kotlin
// 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.
}
2. Execute code in a background thread
Java
// 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);
Kotlin
// 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)
Note: Remember to shut down the executor after using.
backgroundExecutor.shutdown(); // or backgroundExecutor.shutdownNow();
3. Execute code in a background thread and update UI on the main thread.
Java
// 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.
}
});
}
});
Kotlin
// 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.
}
}
Solution 2: Specify a Looper explicitly by using one of the following constructors.
Handler(Looper)
Handler(Looper, Handler.Callback)
1. Execute code in the main thread
1.1. Handler with a Looper
Java
Handler mainHandler = new Handler(Looper.getMainLooper());
Kotlin
val mainHandler = Handler(Looper.getMainLooper())
1.2 Handler with a Looper and a Handler.Callback
Java
Handler mainHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
#Override
public boolean handleMessage(#NonNull Message message) {
// Your code logic goes here.
return true;
}
});
Kotlin
val mainHandler = Handler(Looper.getMainLooper(), Handler.Callback {
// Your code logic goes here.
true
})
2. Execute code in a background thread
2.1. Handler with a Looper
Java
// 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());
Kotlin
// 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)
2.2. Handler with a Looper and a Handler.Callback
Java
// 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;
}
});
Kotlin
// 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
})
Note: Remember to release the thread after using.
handlerThread.quit(); // or handlerThread.quitSafely();
3. Execute code in a background thread and update UI on the main thread.
Java
// 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;
}
});
Kotlin
// 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
})
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.
The deprecated function is that constructor for Handler. Use Handler(Looper.myLooper()) .postDelayed(runnable, delay) instead
Consider using coroutines
scope.launch {
delay(3000L)
// do stuff
}
Using lifecycle scope this is more easy. Inside activity or fragment.
lifecycleScope.launch {
delay(2000)
// Do your stuff
}
or use handler
Handler(Looper.myLooper()!!)
I have 3 solutions:
Specify the Looper explicitly:
Handler(Looper.getMainLooper()).postDelayed({
// code
}, duration)
Specify the implicit thread local behavior:
Handler(Looper.myLooper()!!).postDelayed({
// code
}, duration)
using Thread:
Thread({
try{
Thread.sleep(3000)
} catch (e : Exception) {
throw e
}
// code
}).start()
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);
use this
Looper.myLooper()?.let {
Handler(it).postDelayed({
//Your Code
},2500)
}
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);
Provide a looper in the Handler Constructor
Handler(Looper.getMainLooper())
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
}
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);
}
}
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()
}
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)
}
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);
}
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.
I usually use this one
Code:
Handler(Looper.myLooper() ?: return).postDelayed({
// Code what do you want
}, 3000)
Screenshot:
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...
For Xamarin Android, instead of
Handler handler;
handler = new Handler();
just write
Handler handler;
handler = new Handler(Looper.MyLooper());
the rest of the code is fine.

How to track/manage runnables in Android

In my code I need to implement instant spam action for message. For this I change my message without waiting for server response. But sometime on server request errors I need to revert my message state to original. handler.removeCallbacks(runnable) not letting me know whether runnable has already run. How I can accomplish this? I also open to other suggestions to perform these delayed jobs via RxJava, or other technologies.
var handler = Handler()
fun spamMessage(originalMessage: ContentMessage) {
var runnable: Runnable? = null
val modifiedMessage = originalMessage.cloneUsingJson()
if (modifiedMessage != null) {
modifiedMessage.setSpamReported(true)
runnable = Runnable {
updateMessage(message)
}
updateWithDelay(runnable)
}
ApiClient.service.spamMessage(message.serverId).subscribeAsync(subscriptions, object : ApiSubscriberNew<Void>() {
override fun onFailure() {
var canceled : Boolean = handler.removeCallbacks(runnable)
if (!canceled) {
//if couldn't cancel, or was late, revert the changes
revertMessageUpdate(originalMessage)
}
}
})
}
private fun updateWithDelay(runnable: Runnable) {
handler.postDelayed(runnable, 100)
}

How to check some condition every 1 sec in java until true

I need to check certain condition in java every 1 second until it is true.Once it is true, need to exit from it and proceed further.
Say a->b->c
check b every 1 sec until it is true, if it is true go to c.
Could someone suggest what is the best possible way to achieve this in Java?
Here is what you need:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if(!condition)
handler.postDelayed(this, 1000);
else {
// do actions
condition = true;
}
}
}, 1000);
}
I think you should take a look at the Timer and TimerTask classes. You can use them to schedule certain tasks to take place after a certain amount of time.
You need to extend the 'TimerTask' class and override the run() method. For example, you could do something like this:
Here's an example, which prints Hello World every 5 seconds: -
class CheckCondition extends TimerTask {
public void run() {
// if some condition is true
// do something
}
}
Used from another method, which checks your condition once every second (the function takes milliseconds):
Timer timer = new Timer();
// timer.schedule(class, initial delay, interval in milliseconds)
timer.schedule(new CheckCondition(), 0, 1000);
One option is using the Handler's postDelayed() method:
// do something A
do {
// Execute some code after 1 second has passed
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// do something B
}
}, 1000);
}
while(condition);
// do something C

How do I use a timer to run code again and again until a boolean value e.g. Testing is equal to true?

This is probably a very easy question but, How do I use a timer to run code again and again until a boolean value e.g. Testing is equal to true?
Obviously I would use a while loop but I don't want it to stop the rest of the work taking place on the main ui thread
If your process is running simultaneously, use a Handler and use its postDelayed(Runnable, long) to post a callback implementing the Runnable interface.
A rather naive example:
final handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
if (<EXPRESSION>) {
// Evaluated true, do your stuff and exit the polling loop.
} else {
handler.postDelayed(this, <TIMEOUT>);
}
}
handler.postDelayed(r, <TIMEOUT>);
You can use AlarmManager class to manage your thread. its simple to use.
for more info you can visit Android SDK Doc
timer=new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Do your task
if(flagIsOn)
{
timer.cancel();
timer.purge();
}
}
}, 0, 1000);

What is the equivalent to a JavaScript setInterval/setTimeout in Android/Java?

Can anyone tell me if an equivalent for setInterval/setTimeout exists for Android? Does anybody have any example about how to do it?
As always with Android there's lots of ways to do this, but assuming you simply want to run a piece of code a little bit later on the same thread, I use this:
new android.os.Handler(Looper.getMainLooper()).postDelayed(
new Runnable() {
public void run() {
Log.i("tag", "This'll run 300 milliseconds later");
}
},
300);
.. this is pretty much equivalent to
setTimeout(
function() {
console.log("This will run 300 milliseconds later");
},
300);
setInterval()
function that repeats itself in every n milliseconds
Javascript
setInterval(function(){ Console.log("A Kiss every 5 seconds"); }, 5000);
Approximate java Equivalent
new Timer().scheduleAtFixedRate(new TimerTask(){
#Override
public void run(){
Log.i("tag", "A Kiss every 5 seconds");
}
},0,5000);
setTimeout()
function that works only after n milliseconds
Javascript
setTimeout(function(){ Console.log("A Kiss after 5 seconds"); },5000);
Approximate java Equivalent
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
Log.i("tag","A Kiss after 5 seconds");
}
}, 5000);
If you're not worried about waking your phone up or bringing your app back from the dead, try:
// Param is optional, to run task on UI thread.
Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
#Override
public void run() {
// Do the task...
handler.postDelayed(this, milliseconds) // Optional, to repeat the task.
}
};
handler.postDelayed(runnable, milliseconds);
// Stop a repeating task like this.
handler.removeCallbacks(runnable);
Depending on what you actually want to achieve, you should take a look at Android Handlers:
http://developer.android.com/reference/android/os/Handler.html
If you previously used javascript setTimeout() etc to schedule a task to run in the future, this is the Android way of doing it (postDelayed / sendMessageDelayed).
Note that neither Handlers or Timers makes an Android phone wake up from sleep mode. In other words, if you want to schedule something to actually happen even though the screen is off / cpu is sleeping, you need to check out the AlarmManager too.
The first answer is definitely the correct answer and is what I based this lambda version off of, which is much shorter in syntax. Since Runnable has only 1 override method "run()", we can use a lambda:
this.m_someBoolFlag = false;
new android.os.Handler().postDelayed(() -> this.m_someBoolFlag = true, 300);
I do not know much about JavaScript, but I think Timers may be what you are looking for.
http://developer.android.com/reference/java/util/Timer.html
From the link:
One-shot are scheduled to run at an absolute time or after a relative delay. Recurring tasks are scheduled with either a fixed period or a fixed rate.
import java.util.Timer;
import java.util.TimerTask;
class Clock {
private Timer mTimer = new Timer();
private int mSecondsPassed = 0;
private TimerTask mTask = new TimerTask() {
#Override
public void run() {
mSecondsPassed++;
System.out.println("Seconds passed: " + mSecondsPassed);
}
};
private void start() {
mTimer.scheduleAtFixedRate(mTask, 1000, 1000);
}
public static void main(String[] args) {
Clock c = new Clock();
c.start();
}
}
I was creating a mp3 player for android, I wanted to update the current time every 500ms so I did it like this
setInterval
private void update() {
new android.os.Handler().postDelayed(new Runnable() {
#Override
public void run() {
long cur = player.getCurrentPosition();
long dur = player.getDuration();
currentTime = millisecondsToTime(cur);
currentTimeView.setText(currentTime);
if (cur < dur) {
updatePlayer();
}
// update seekbar
seekBar.setProgress( (int) Math.round((float)cur / (float)dur * 100f));
}
}, 500);
}
which calls the same method recursively
Here's a setTimeout equivalent, mostly useful when trying to update the User Interface
after a delay.
As you may know, updating the user interface can only by done from the UI thread.
AsyncTask does that for you by calling its onPostExecute method from that thread.
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// Update the User Interface
}
}.execute();
As always with Android there's lots of ways to do this, but assuming you simply want to run a piece of code on the same thread, I use this:
new Timer().scheduleAtFixedRate(new TimerTask(){
#Override
public void run(){
Log.i("tag", "Hai Codemaker");
}
},0,1000);
This code will log Hai Codemaker text every one second.
Kotlin:
You can also use CountDownTimer:
class Timer {
companion object {
#JvmStatic
fun call(ms: Long, f: () -> Unit) {
object : CountDownTimer(ms,ms){
override fun onFinish() { f() }
override fun onTick(millisUntilFinished: Long) {}
}.start()
}
}
}
And in your code:
Timer.call(5000) { /*Whatever you want to execute after 5000 ms*/ }
In case someone wants -
Kotlin equivalent to JavaScript setInterval/setTimeout
IMPORTANT: Remember to import android.os.Handler. Don't get mistaken by java.util.logging.Handler
Timeout equivalent
Javascript: setTimeout()
setTimeout(function(){
// something that can be run.
}, 1500);
Kotlin: runOnTimeout()
inline fun runOnTimeout(crossinline block: () -> Unit, timeoutMillis: Long) {
Handler(Looper.getMainLooper()).postDelayed({
block()
}, timeoutMillis)
}
Kotlin: Calling
runOnTimeout({
// something that can be run.
}, 1500)
Timeinterval equivalent
Javascript: setInterval()
setInterval(function(){
// something that can be run.
}, 1500);
Kotlin: runOnInterval()
inline fun runOnInterval(crossinline block: () -> Unit, interval: Long) {
val runnable = object : Runnable {
override fun run() {
block()
handler.postDelayed(this, interval)
}
}
handler.post(runnable)
}
Kotlin: Calling
runOnInterval({
// something that can be run.
}, 1500)
Cancellable timeout and interval
If you want to use custom handler so that you can cancel the runnable, then you can use following codes.
Timeout
inline fun runOnTimeout(crossinline block: () -> Unit, timeoutMillis: Long) {
runOnTimeout(Handler(Looper.getMainLooper()), block, timeoutMillis)
}
inline fun runOnTimeout(handler: Handler, crossinline block: () -> Unit, timeoutMillis: Long): Runnable {
val runnable = Runnable { block() }
handler.postDelayed(runnable, timeoutMillis)
return runnable
}
Timeout: Calling
runOnTimeout({
// something that can be run.
}, 1500)
// OR
val runnable = runOnTimeout(mHandler, {
// something that can be run.
}, 1500)
// to cancel
mHandler.removeCallbacks(runnable)
Interval
inline fun runOnInterval(crossinline block: () -> Unit, interval: Long) {
runOnInterval(Handler(Looper.getMainLooper()), block, interval)
}
inline fun runOnInterval(handler: Handler, crossinline block: () -> Unit, interval: Long): Runnable {
val runnable = object : Runnable {
override fun run() {
block()
handler.postDelayed(this, interval)
}
}
handler.post(runnable)
return runnable
}
Interval: Calling
runOnInterval({
// something that can be run.
}, 1500)
// OR
val runnable = runOnInterval(mHandler, {
// something that can be run.
}, 1500)
// to cancel
mHandler.removeCallbacks(runnable)

Categories

Resources