My question is very similar to this question, except that I need it to work with fragments instead of Views.
As explained in that thread, there seems to be a bug(?) in Android when an AnimationListener is attached to an Animation, which results in the onAnimationEnd() callback getting called before the animation has really completely ended.
I'm using fullscreen fragments which are animated in the FragmentTransaction (v4 support library) to have a horizontal "roll-in" effect. This works smoothly everywhere except in the fragment where I start a camera preview. Therefore I want to only start the camera preview once the animation is finished.
I tried using this method in my Fragment:
@Override
public Animation onCreateAnimation(final int transit,final boolean enter,final int nextAnim)
{
Animation anim=super.onCreateAnimation(transit, enter, nextAnim);
if (anim==null && nextAnim!=0)
anim=AnimationUtils.loadAnimation(getActivity(), nextAnim);
if(anim!=null)
{
anim.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation)
{
}
@Override
public void onAnimationRepeat(Animation animation)
{
}
@Override
public void onAnimationEnd(Animation animation)
{
scannerView.startCameraInHandlerThread();
}
});
}
Unfortunately starting the camera is quite an expensive operation and so my animation lags every time right before the animation is over. It looks ugly and my client is complaining about it.
I also thought about a cheap solution like waiting/sleeping on the camera thread, but the main thread actually needs to wait for the camera starting thread for synchronization otherwise it can deadlock in some cases, so sleeping actually makes the issue worse (the lag becomes longer).
Does anyone know how to solve this?
edit: someone asked for more code...
public void startCameraInHandlerThread()
{
if (mThread == null)
mThread = new CameraHandlerThread();
synchronized (mThread) {
mThread.openCamera();
}
}
private class CameraHandlerThread extends HandlerThread
{
Handler mHandler = null;
CameraHandlerThread()
{
super("CameraHandlerThread");
start();
mHandler = new Handler(getLooper());
}
synchronized void notifyCameraActionCompleted() {
notify();
}
void openCamera()
{
mHandler.post(new Runnable() {
@Override
public void run() {
startCamera();
notifyCameraActionCompleted();
}
});
try
{
wait();
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
LOG.warn("Waiting for camera opening was interrupted");
}
}
}