Handler.postDelayed和方向更改问题

时间:2014-10-04 11:53:42

标签: android handler

我面临一个我无法解决的奇怪问题。问题是,我有一个活动,按下按钮后我改变了一些布局的可见性。之后,我使用Handler以便在4秒后恢复该情况,并将所有内容放在原来的位置。

一切都按预期工作,除非我更改设备方向,如果我在此过程中更改设备方向,我的视图将无法恢复,我不确定问题出在哪里:S。

以下是相关代码

private View mLoginFormView;
private View mLoginStatusView;
private boolean mLogginIn = false;


@Override
protected void onCreate(Bundle savedInstanceState) {
    Log.d(TAG, "onCreate");

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_login_layout);

    mLoginFormView = findViewById(R.id.login_form);
    mLoginStatusView = findViewById(R.id.login_status);

    if (savedInstanceState == null) {
        mLogginIn = false;


    } else {

        mLogginIn = savedInstanceState.getBoolean(getString(R.string.user_login_in),false);
        Log.d(TAG,"RESTORING MLOGIN IN = " + mLogginIn);
    }

    findViewById(R.id.sign_in_button).setOnClickListener(
            new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                    attemptLogin();
                }
            });

    if(mLogginIn)
        showProgress(true);
}

现在我介绍相关的功能

//.......

public void attemptLogin() {

    showProgress(true);
    mMenu.findItem(R.id.started).setVisible(false);

    Handler handler = new Handler();

    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    showProgress(false);
                    Log.d(TAG,"MLOGGIN VALUE PROGRESS = " + mLogginIn);
                    mLogginIn = false;
                }
            });

        }
    },4000);
}

ShowProgress()

private void showProgress(final boolean show) {
    mLogginIn = show;
    Log.d(TAG, "showProgress " + mLogginIn);

    int shortAnimTime = getResources().getInteger(
            android.R.integer.config_shortAnimTime);

    mLoginStatusView.setVisibility(View.VISIBLE);
    mLoginStatusView.animate().setDuration(shortAnimTime)
    .alpha(show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            mLoginStatusView.setVisibility(show ? View.VISIBLE
                    : View.GONE);
        }
    });

    mLoginFormView.setVisibility(View.VISIBLE);
    mLoginFormView.animate().setDuration(shortAnimTime).alpha(show ? 0 : 1)
    .setListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            mLoginFormView.setVisibility(show ? View.GONE
                    : View.VISIBLE);
        }
    });
}

最奇怪的是,在执行onRestoreInstanceState代码后调用postDelayed时,mLogginIn显示前一个值(true),就好像它没有效果一样所有

提前致谢

2 个答案:

答案 0 :(得分:4)

由于配置更改而重新创建Activity时,它是一个完全不同的对象实例,具有另一个嵌入式视图层次结构。您的Handler对旧对象实例很紧张,因此它也会修改旧的视图层次结构。因此,你什么也看不见。

不要这样做:它会泄漏内存并可能导致崩溃。

解决方案

  1. 发布Runnable时,请将Runnable实例和当前时间戳保存在两个引用中。如果Runnable正常运行,请将时间戳设置为-1(在Runnable代码中)。

  2. 如果时间戳与-1不同,则在onSaveInstanceState(Bundle)上保留配置更改,并使用Handler.removeCallbacks(Runnable)从处理程序中删除可运行的回调。

  3. 重新创建活动时,恢复时间戳并计算与当前时间的差异。使用此延迟发布具有相同逻辑的新Runnable(如果它为0或否定,您可能希望直接运行runnable而不是发布它)。此Runnable现在对Activity的新实例很紧张。

答案 1 :(得分:1)

当设备方向改变时,您的活动将被销毁,并且会创建新活动并通过savedInstanceState包恢复状态。但是你使用postDelayed发布的runnable是一个与原始活动相关的匿名内部类。此活动对象仍然存在,您的runnable会修改它,但它不再可见。

您当前的架构不起作用,您必须选择其他架构才能达到您想要的效果。