在允许用户通过社交网络登录的android应用程序中,我使用以下代码显示并隐藏aFAB
android - 使用AnimationUtils显示和隐藏FAB时的竞争条件-LMLPHP

public abstract class LoginFragment extends Fragment {

    private FloatingActionButton mFab;
    private Animation mShowFab;
    private Animation mHideFab;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mShowFab = AnimationUtils.makeInAnimation(getContext(), false);
        mShowFab.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                mFab.setVisibility(View.VISIBLE);
            }

            @Override
            public void onAnimationEnd(Animation animation) {
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });

        mHideFab = AnimationUtils.makeOutAnimation(getContext(), true);
        mHideFab.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                mFab.setVisibility(View.INVISIBLE);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
    }

    private void showFab(boolean show) {
        boolean visible = mFab.isShown();

        if (show && !visible) {
                mFab.startAnimation(mShowFab);
        } else if (!show && visible) {
                mFab.startAnimation(mHideFab);
        }
    }

当我调用上面的showFab方法足够慢时,这很好。
在开始任何动画之前,我检查当前FloatingActionButton可见性,以便动画只播放一次-即使我连续多次调用showFab(true)
我的问题:
当我的应用程序中显示aLoginFragment时,我首先向aServiceIntent发送请求以从sqlite获取用户数据,并调用以下方法将我的ui设置为“等待”状态:
private void setBusy(boolean busy) {
    mProgressBar.setVisibility(busy ? View.VISIBLE : View.INVISIBLE);
    showFab(!busy);
}

几乎立即,sqlite的响应返回-通过LocalBroadcastManager并再次调用上面的方法:setBusy(false)
然后发生错误,FAB不可见。
如果我用无动画代码替换FAB方法,一切正常:
private void showFab(boolean show) {
    mFab.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
}

但有了动画-赛车的情况似乎发生了。
作为解决方法,我尝试取消两个动画-但这无助于:
private void showFab(boolean show) {
    mShowFab.cancel();
    mShowFab.reset();

    mHideFab.cancel();
    mHideFab.reset();

    boolean visible = mFab.isShown();

    if (show && !visible) {
            mFab.startAnimation(mShowFab);
    } else if (!show && visible) {
            mFab.startAnimation(mHideFab);
    }
}

请建议在这里可以做些什么。
我已经在调试器中多次使用我的应用程序。当显示片段时,setBusy(和showFab)只调用两次,但两次调用都发生得非常快,FAB没有显示-
第一次运行:
android - 使用AnimationUtils显示和隐藏FAB时的竞争条件-LMLPHP
第二轮:
android - 使用AnimationUtils显示和隐藏FAB时的竞争条件-LMLPHP
更新:
不幸的是,使方法synchronized也没有帮助-FAB保持隐藏:
private synchronized void showFab(boolean show) {
    mShowFab.cancel();
    mShowFab.reset();

    mHideFab.cancel();
    mHideFab.reset();

    boolean visible = mFab.isShown();

    if (show && !visible) {
        mFab.startAnimation(mShowFab);
    } else if (!show && visible) {
        mFab.startAnimation(mHideFab);
    }
}

最佳答案

每个动画都在不同的线程中运行。正如你所说,这会导致一种种族状况。
下面是发生的事情:
showfab是用true,然后用false触发的。
mshowfab onanimationstart方法执行并将fab设置为可见。
mhidefab onanimationstart方法执行而不执行任何操作。
mshowfab onanimationend方法执行而不执行任何操作。
mhidefab onanimationend方法执行并将fab设置为不可见。
最后你会发现一个不可见的晶圆厂应该是可见的。
第二次运行中的变量显示mshowfab动画永远不会运行。
您应该能够通过监听隐藏动画的结尾来解决竞赛条件。像这样的:

private void showFab(boolean show) {
    if (show) {
        // if you have an animation currently running and you want to show the fab
        if (mFab.getAnimation() != null && !mFab.getAnimation().hasEnded()) {
            // then wait for it to complete and begin the next one
            mFab.getAnimation().setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    mFab.setVisibility(View.INVISIBLE);
                    mFab.startAnimation(mShowFab);
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
        } else {
            mFab.startAnimation(mShowFab);
        }
    } else {
        mFab.startAnimation(mHideFab);
    }
}

07-24 09:49
查看更多