I'm trying to produce an animation with delay less than 1 milli second.
Based on my research, I found some answers about ScheduledThreadPoolExecutor.
Unfortunately, I applied the following code but it's not working as I expected..
public class MainActivity extends Activity {
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
private Handler mHandler = new Handler();
public void buttonClicked(View v){
if(v.getId() == R.id.start_animation)
{
//Case1
mHandler.post(animateImage);
//Case2
//startEffect();)
}
}
private Runnable animateImage = new Runnable() {
#Override
public void run() {
runOnUiThread(
new Runnable()
{
public void run()
{
doTheAnimation1();
}
});
}
};
private void doTheAnimation1() {
doFlipImage();
}
private void startEffect()
{
long delay = 1000; //the delay between the termination of one execution and the commencement of the next
exec.scheduleAtFixedRate(animateImage, 0, delay, TimeUnit.MICROSECONDS);
}
}
According to the code, once the button is clicked the mHandler will call the animateImage, animateImage will doFlipImage which will create a Bitmap and assign it to the canvas and I start drawing over that canvas, and this bitmap will be used to invalidate an imageview.
if I'm using mHandler then everythings works fine, but if I'm using ScheduledThreadPoolExecutor (so I will call startEffect method instead of mHandler.post), then the imageview appears white after the drawings happened as I guess, How could I solve this issue.
Related
I am having trouble with a TimerTask Interfering with In App Purchasing (Async Tasks).
I am weak with Threads, so I believe it is running on the main UI thread, eating up resources.
How can I run this outside the UI thread? I have searched, and tried some suggestions using handlers. but seems like I get the same result, app gets really laggy.
when I don't run this task (refreshes every 500mS), the activity runs smoothly, and there are no hangs during In app purchases.
Your help is appreciated, code snippet below:
public class DummyButtonClickerActivity extends Activity {
protected Timer timeTicker = new Timer("Ticker");
private Handler timerHandler = new Handler();
protected int timeTickDown = 20;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainhd);
// start money earned timer handler
TimerTask tick = new TimerTask() {
public void run() {
myTickTask();
}
};
timeTicker.scheduleAtFixedRate(tick, 0, 500); // 500 ms each
} // End OnCreate
protected void myTickTask() {
if (timeTickDown == 0) {
/// run my code here
//total = total + _Rate;
timerHandler.post(doUpdateTimeout);
}
else if(timeTickDown < 0) {
// do nothing
}
timeTickDown--;
}
private Runnable doUpdateTimeout = new Runnable() {
public void run() {
updateTimeout();
}
};
private void updateTimeout() {
// reset tick
timeTickDown = 2; // 2* 500ms == once a second
}
}
You can use HandlerThread that will run your Handler on a separate Thread
documentation:
Handy class for starting a new thread that has a looper.
The looper can then be used to create handler classes. Note that start() must still be called.
example:
HandlerThread mHandlerThread = new HandlerThread("my-handler");
mHandlerThread.start();
Handler mHandler = new Handler(mHandlerThread.getLooper());
update:
private Runnable doUpdateTimeout;
private HandlerThread mHandlerThread;
private Handler timerHandler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainhd);
// start money earned timer handler
TimerTask tick = new TimerTask() {
public void run() {
myTickTask();
}
};
mHandlerThread = new HandlerThread("my-handler");
mHandlerThread.start();
timerHandler = new Handler(mHandlerThread.getLooper());
doUpdateTimeout = new Runnable() {
public void run() {
updateTimeout();
}
};
timeTicker.scheduleAtFixedRate(tick, 0, 500); // 500 ms each
} // End OnCreate
protected void myTickTask() {
if (timeTickDown == 0) {
/// run my code here
//total = total + _Rate;
timerHandler.post(doUpdateTimeout);
}
else if(timeTickDown < 0) {
// do nothing
}
timeTickDown--;
}
private void updateTimeout() {
// reset tick
timeTickDown = 2; // 2* 500ms == once a second
}
}
when you want to update the TextView from different thread
call this:
YOU_ACITIVITY_CLASS.this.runOnUiThread(new Runnable() {
#Override
public void run() {
//update here
}
});
The handler is running and processing in the main ui thread,so the method doUpdateTimeout will be executed in the main thread.
In your code, after running 10 seconds later,the timeTickDown equals to 0 and code timerHandler.post(doUpdateTimeout); will be invoked,which will be executed in the main thread. Because it just let timeTickDown = 2; one second later,this code will be executed again(in the main ui thread) and then go on in each second.If there is some other code in doUpdateTimeout or updateTimeout,your main thread will be laggy.
Just change timerHandler.post(doUpdateTimeout); to updateTimeout()(call it directly and then execute it in the Timer thread,not the main ui thread).
I am using a handler to call runnable after a delay of 5 seconds. this then calls a method in a custom view. the problem im having is that the method is being called but the delay is far greater than 5 seconds.
code is as follows.
final Handler h = new Handler();
h.postDelayed(new Runnable()
{
#Override
public void run()
{
buttonArray.get(1).activate();
}
}, 5000);
and the code in the custom view that is being called
public void activate()
{
active = true;
this.animate().alpha(0.4f).setDuration(150);
}
Thanks
I want to cyclically update an Android Layout. For this purpose I wrote a short class derived from TimerTask.
Unfortunately my code causes an exception and I do not really know, what the problem might be. :(
So maybe anybody could help.
Thanks
Chris
Here's my code:
In the main activity I've got:
private MyLayoutClass m_MyLayout;
...
public void onCreate(Bundle savedInstanceState)
{
...
m_MyLayout = new AdLayout(this);
Timer caretaker = new Timer();
caretaker.schedule(new MyReloadTimerTask(m_MyLayout), 1000, 5000);
...
}
This is my derived TimerTask class:
public class MyReloadTimerTask extends TimerTask
{
private MyLayoutClass m_MyLayout;
public MyReloadTimerTask(MyLayoutClass aLayout)
{
m_MyLayout = aLayout;
}
#Override
public void run()
{
m_MyLayout.doReload();
}
}
The doReload() cannot be executed, I get an exception with this message: Can't create handler inside thread that has not called Looper.prepare()
Timertask runs on a different thread. So you cannot not update/access ui from a background thread.
Probably m_MyLayout.doReload() is updating ui. Use a Handler or runOnUiThread
runOnUiThread(new Runnable() {
#Override
public void run() {
m_MyLayout.doReload()
}
});
Using Handler
Handler m_handler;
Runnable m_handlerTask ;
m_handler = new Handler();
m_handlerTask = new Runnable()
{
#Override
public void run() {
// do something
m_handler.postDelayed(m_handlerTask, 1000);
// repeat some task every 1 second
}
};
m_handlerTask.run();
To cancel the run
m_handler.removeCallbacks(m_handlerTask);
I am working on a layout which shows a tab like structure on bottom of the layout. Which I need to show on double tap and then hide it after 5 sec. So I am using this countdown timer:
public void timer()
{
cdt=new CountDownTimer(5000,1000) {
#Override
public void onTick(long millisUntilFinished) {
System.out.println("Timer Working"+millisUntilFinished+"");
}
#Override
public void onFinish() {
System.out.println("Finished");
main =(LinearLayout)findViewById(R.id.parent);
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)main.getLayoutParams();
mlp.height=420;
set_up_views();
find_module();
tl.setVisibility(View.INVISIBLE);
}
}.start();
}
But I dont know how to stop and restart this timer. How can I do?
I suggest you not to Use CountDownTimer for this case.
Use Handler.postDelayed(Runnable runnable, long delay)
public class yourActivity extends Activity
{
public Handler handler = new Handler();
...
public void hideAfter5Sec()
{
handler.postDelayed(new Runnable()
{
View view = findViewById(view_to_hide);
view.setVisibility(View.INVISIBLE);
}, 5000);
}
}
postDelayed will execute that code after 5Sec.
EDITED:
postDelayed will be call only once after 5 Sec through Lopper.loop(). If there are multiple call to hideAfter5Sec() then only you will get multiple call to postDelayed.
If you have multiple call hideAfter5Sec() i dont think there is any wrong because hideAfter5Sec() is just hidding it. so if it one or many your view will be hidden.
If in case you want to hide only in the last call of hideAfter5Sec() use this variant.
public class yourActivity extends Activity
{
public Handler handler = new Handler();
public long lastHideAfter5Sec = 0L;
...
public void hideAfter5Sec()
{
lastHideAfter5Sec = System.currentTimeMillis();
handler.postDelayed(new Runnable()
{
if(System.currentTimeMillis() - lastHideAfter5Sec < 5000)
return;
View view = findViewById(view_to_hide);
view.setVisibility(View.INVISIBLE);
}, 5000);
}
I'm developing a Service for Android, that must run in background, executing a function each 100 seconds. That's the source code (example)
package com.example
import ....
public class Servizio extends Service {
public IBinder onBind(Intent intent) {
}
public void onCreate() {
}
public void onDestroy() {
//here put the code that stop the timer cycle
}
public void onStart(Intent intent, int startid) {
//i want to begin here the timercycle that each 100 s call myCycle()
}
public void myCycle() {
//code that i can't move on other class!!!
}
}
How I can do that? Now the service execute myCycle() just one time, beacause I put a calling in onStart().
Use a Timer with a TimerTask. To execute your method every 100 seconds, you can use the following in your onStart method. Be aware that this method creates a new thread.
new Timer().schedule(new TimerTask() {
#Override
public void run() {
myCycle();
}
}, 0, 100000);
Alternatively, use an android.os.Handler as described in this article: Updating the UI from a Timer. It is better than a Timer because it runs in the main thread, avoiding the overhead of a second thread.
private Handler handler = new Handler();
Runnable task = new Runnable() {
#Override
public void run() {
myCycle();
handler.postDelayed(this, 100000);
}
};
handler.removeCallbacks(task);
handler.post(task);
I usually do this, if I understood correctly you wanted the myCycle to execute every 100 secs.
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
myCycle();
}
}, 0,100000);
When I had this issue, where I call out to a webservice on a periodic basis this was my solution:
public class MyService extends Service {
private Handler mHandler = new Handler();
public static final int ONE_MINUTE = 60000;
private Runnable periodicTask = new Runnable() {
public void run() {
mHandler.postDelayed(periodicTask, 100 * ONE_MINUTE);
token = retrieveToken();
callWebService(token);
}
};
I call the postDelayed early so that the delay from the webservice call doesn't cause the timing to shift.
The two functions are actually in the MyService class.
UPDATE:
You can pass a Runnable to postDelayed as shown here:
http://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable, long)
public final boolean postDelayed (Runnable r, long delayMillis)
Since: API Level 1 Causes the Runnable r to be added to the message
queue, to be run after the specified amount of time elapses. The
runnable will be run on the thread to which this handler is attached.
Also, my code won't compile due to missing functions, this is shown as an example of what the OP can do.