I have problem with Thread in Java. I want to make when the button (bt1) is clicked to set Background to picture, then wait for 5 seconds and the set Background of the same button to pic. The problem is that the first picture has never been set. The program just wait 5 seconds and set picture2. Here is the code.
bt1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bt1.setBackgroundResource(R.drawable.picture);
try
{
Thread.sleep(5000);
}
catch( InterruptedException e )
{
e.printStackTrace();
}
bt1.setBackgroundResource(R.drawable.pic);
}
});
}
Never, ever sleep the user interface thread!
The problem is that you are sleeping in the thread that handles reacting to GUI events. While that thread sleeps, the GUI is dead. You need to do something else to get your five second delay, such as using a Timer to create a new event in 5 seconds.
Try this:
public void onClick(View v) {
bt1.setBackgroundResource(R.drawable.picture);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
bt1.setBackgroundResource(R.drawable.picture);
}
}, 5000);
}
It because you are running everything on main UI thread. Never use sleep with UI thread.
here is code for you.
public void onClick(View v) {
bt1.setBackgroundResource(R.drawable.picture);
Thread thread = new Thread()
{
#Override
public void run() {
try {
Thread.sleep(5000);
runOnUiThread(new Runnable(){public void run()
{
bt1.setBackgroundResource(R.drawable.pic);
}});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}
});
Use countdowntimer
new CountDownTimer(5000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
bt1.setBackgroundResource(R.drawable.picture);
}
}.start();
Use Handlder.PostDelayed(), and never do the time-consuming operation in UI Thread such as sleep, network, datebase...
Why not use scheduler?Here is a possible implementation
bt1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bt1.setBackgroundResource(R.drawable.picture);
ScheduledExecutorService scheduler = Executors
.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
bt1.setBackgroundResource(R.drawable.pic);
}
}, 5, 60, TimeUnit.SECONDS);
bt1.setBackgroundResource(R.drawable.pic);
}
});
}
Related
I am trying to use swipe refresh layout to update some data.
All works fine but a small bug that I can't seem to solve
When I pull to refresh, the animation gets frozen.
I have implemented it this way:
myRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// Do some stuff
// Sleep as a demonstrator of the issue
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
myRefreshLayout.setRefreshing(false);
}
});
and also tried this:
myRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
myRefreshLayout.post(new Runnable() {
#Override
public void run() {
// Do some stuff
// Sleep as a demonstrator of the issue
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
myRefreshLayout.setRefreshing(false);
}
});
}
});
}
});
but the animation remains frozen until the everything is done, and then it just vanishes (because it hits the setRefreshing(false))
After searching a little, I thought it could be the UI that is waiting for the stuff to finish, so I tried to implement it this way:
myRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
new Thread(new Runnable() {
#Override
public void run() {
// Do some stuff
// Sleep as a demonstrator of the issue
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
myRefreshLayout.setRefreshing(false);
}
});
}
});
}
});
}
What happens in this case is that the refresh indicator never vanishes, so I guess it is not calling the runOnUiThread
I tried the same thing with the main looper (handler) instead of the runOnUiThread with the same effect.
Is there any neat way of implementing this?
Am I missing some detail?
I tried the steps described above and I also looked on Stack Overflow for similar issues to no avail.
Thanks!
It's right to do refreshing on background thread,and setRefreshing(false) on main thread. The problem is you forgot to call start() after new thread.
myRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
new Thread(new Runnable() {
#Override
public void run() {
// Do some stuff
// Sleep as a demonstrator of the issue
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
myRefreshLayout.setRefreshing(false);
}
});
}
}).start();// start the thread here
}
});
}
After click button I would like to change its color, then wait one second and change its color back.
This is my code:
public void click(final View view) throws InterruptedException {
final Button btn = findViewById(view.getId());
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
t.join();
btn.setBackgroundColor(Color.parseColor("#e2e2e2"));
btn.setClickable(true);
}
It doesn't work. I've checked it with more complex code and debugger and it looks like all UI changes are made collectively after finish this function.
I've found this thread: apply ui changes immediately and tried to put setBackgroundColor() and setClickable() into runOnUiThread function:
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
}
});
But it also doesn't work. What should I do?
Something like this :
private final Handler handler = new Handler();
public void click(final View view) {
view.setBackgroundColor(Color.parseColor("#0000ff"));
view.setClickable(false);
handler.postDelayed(() -> {
view.setBackgroundColor(Color.parseColor("#e2e2e2"));
view.setClickable(true);
}, 1000);
}
#Override protected void onPause() {
super.onPause();
handler.removeCallbacks(null);
}
The question is not very clear. However, I am trying to summarize the question that I have understood from your question.
You are trying to set a button's background color on clicking on it and change it back after some time. If this is the situation, then I think your idea of how threads work is wanting.
In your code, the button will change the color immediately as the sleep that you are using is running in another thread (other than UI thread). The code is executed correctly, however, you cannot see the effect of the Thread.sleep as its running in a separate thread.
So all you need to do here is to change the background color again inside the thread. Modify your code like the following.
public void click(final View view) throws InterruptedException {
final Button btn = findViewById(view.getId());
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
btn.setBackgroundColor(Color.parseColor("#e2e2e2"));
btn.setClickable(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
This should work.
I have created a demo trying to show what the code will do.
However, using Handler in case of updating UI elements in this specific case is recommended. Please see the comments below.
public void click(final View view) throws InterruptedException {
final Button btn = findViewById(view.getId());
btn.setBackgroundColor(Color.parseColor("#0000ff"));
btn.setClickable(false);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
btn.setBackgroundColor(Color.parseColor("#e2e2e2"));
btn.setClickable(true);
}
}, 1000);
}
Not sure why that wouldn't work, but I've done something similar with
delayHandler = new Handler();
delayHandler.postDelayed(new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//change stuff on ui
}
});
}
}, 1000);
if that doesn't work the only other functional difference in my code is that instead of btn being a final Button it's a private global variable in my activity.
Hope the following code will help :
btn.setBackgroundColor(Color.RED); // color you want for a second
new CountDownTimer(1000, 1000) {
#Override
public void onTick(long arg0) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
btn.setBackgroundColor(Color.BLUE); //to change back color to prior state
}
}.start();
Try this,i think it's work for you..
final Button bPdf = findViewById(R.id.pdf);
bPdf.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
bPdf.setBackgroundColor(Color.parseColor("#0000ff"));
new CountDownTimer(1000, 50) {
#Override
public void onTick(long arg0) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
bPdf.setBackgroundColor(Color.parseColor("#e2e2e2"));
}
}.start();
}
});
I have two Buttons in main View, Button1 and Button2. How can I disable Button1 for specific time period after that time period it should Enable again.
Use a countdown Timer.
Say you have button button1 ;
button1.setEnabled(false);
new CountDownTimer(5000, 10) { //Set Timer for 5 seconds
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
button1.setEnabled(true);
}
}.start()
Aba: Applied correct View.setEnabled method.
Here is an example:
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
#Override
public void run(){
button.setEnabled(false);
}
}, 5000);
Rest, figure out yourself.
You can call this method. Try this once
private void blink(){
final Handler handler = new Handler();
new Thread(new Runnable() {
#Override
public void run() {
int timeToBlink = 5000;
try{
Thread.sleep(timeToBlink);
}catch (Exception e) {
}
handler.post(new Runnable() {
#Override
public void run() {
if(button.isEnabled()){
button.setEnabled(false);
}else{
button.setEnabled(true);
}
blink();
}
});
}
}).start();
}
By calling this method You will get the effect you wanted
private fun initButton() {
button.setOnClickListener {
it.isEnabled = false
it.postDelayed({ it.isEnabled = true }, 3000)
//do stuff
}
}
This works in Kt, does require a handler tho
In the simplest way
yourView.setEnabled(false);
yourView.postDelayed(() -> yourView.setEnabled(true), 5000); // Wait for 5 seconds
I'm programming a small android app in Java/eclipse.
In one part of my app i need a thread, as i build in the following way:
protected void onResume() {
super.onResume();
// we're going to simulate real time with thread that append data to the graph
new Thread(new Runnable() {
#Override
public void run() {
// we add 100 new entries
for (int i = 0; i < 100; i++) {
runOnUiThread(new Runnable() {
#Override
public void run() {
addEntry();
}
});
// sleep to slow down the add of entries
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// manage error ...
}
}
}
}).start();
}
Evertything works fine so far. But now i want to start that thread not automatically. I want to handle ".start()" with a button.
How can i realize it?
I'm very new to Java and Android.
Thanks in Advance!
You can use Handler with Runnable instead of your Thread idea, Check out the following code, it server your purpose,
private Handler broadcastHandler;
private Runnable broadcastRunnable;
protected void onResume() {
super.onResume();
broadcastRunnable = new Runnable() {
#Override
public void run() {
// Your UI related operations
runOnUiThread(new Runnable() {
#Override
public void run() {
addEntry();
}
});
// Add some delay
broadcastHandler.postDelayed(broadcastRunnable, 1000);
}
}
public void onButtonClick(View view) {
broadcastHandler.postDelayed(broadcastRunnable, 1000);
}
I am working on an Android application in which I allow the users to enter text as many time they want in a single minute. But the thread is not terminating after a minute. My code:
public void startTimer(View view) throws Exception {
final Thread t = new Thread(new Runnable() {
final Button myButton = (Button) findViewById(R.id.myButton);
EditText mEdit = (EditText) findViewById(R.id.myTextInput);
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
myButton.setOnClickListener(
new Button.OnClickListener() {
public void onClick(View v) {
Log.d("Tag", mEdit.getText().toString());
}
}
);
}
}
});
t.start();
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.schedule(new Runnable() {
#Override
public void run() {
t.interrupt();
}
},1, TimeUnit.MINUTES);
}
better use CountDownTimer http://developer.android.com/reference/android/os/CountDownTimer.html
In your solution you try do something with UI state in not main thread - this can be a issue.
Your thread isn't "taking input". It's continuously making and installing new onClick listeners.
You don't need a thread for what you're trying to do. You need a timer that goes off after one minute, and you need a listener that either accepts the input or rejects it depending on whether the timer has gone off yet or not.
You have two solutions you can do:
1st Solution:
You can simply use a handler.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
t.interrupt();
}
}, 60000);
2nd Solution:
You can also use a CountDownTimer.
new CountDownTimer(60000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
t.interrupt();
}
}.start();