【问题标题】:Android : Switch (ToggleButton) and threadsAndroid : 开关 (ToggleButton) 和线程
【发布时间】:2012-12-06 15:49:41
【问题描述】:

在我面向 Android 4.0.3 的应用中,我曾经有一个 Button 作为 Switch。单击按钮正在更改其资源(在播放/暂停之间切换),并且一些任务正在后台执行。特殊之处在于,当按下按钮时,我希望切换开关在短时间内不可用(以防止快速切换)。

为此,我创建了一个等待 X 秒的线程,如下所示:

void blockButton(){
    new Thread() {
        public void run(){
            try {
                        synchronized(this){
                             button_ready = false;
                             sleep(5000);
                             button_ready = true;
                        }
                }
                catch(InterruptedException ex){}
            }
        }.start();
    }
}

基本上在我的 Activity/onClickListener 中

if(button_ready){
    // Start background stuff
    changeButtonResource();
    button.setEnabled(false);
    blockButton();
    button.setEnabled(true);
}

到目前为止一切顺利,一切顺利。但我最终希望将其更新为 Switch。代码几乎相同(除了 onClickListener 变成了 OnCheckedChangeListener)。

但是现在,当我单击一次按钮时,再次单击将允许更改其资源 - 但后台任务将无法启动(我已经使用振动器和其他人尝试过,它只会更改资源)。

所以我几乎拥有了我的 Button 曾经的行为,但是资源变得混乱了。任何想法都会受到欢迎!谢谢。

【问题讨论】:

  • 您的同步块不做任何事情(this 指的是线程,它是一个局部变量,因此不共享)。 button_ready 是如何声明的? volatile?
  • button_ready 是类中的常规变量,并在 onCreate() 方法中初始化。该方法再次与一个简单的 Button 完美配合,因此线程确实做了一些事情(更改 var、等待、更改 var)。
  • 为了使您的代码线程安全(这可能会或可能不会解决问题):删除同步块并将您的变量声明为易失性:private volatile boolean button_ready;
  • 感谢您的提示(虽然没有解决问题)

标签: android multithreading layout button toggle


【解决方案1】:

您不需要创建另一个线程。 View.postDelayed(Runnable) 为您提供了一种在超时后启用按钮(或执行其他 UI 操作)的更简单方法。您的代码应如下所示:

class ... extends Fragment {
    private final Runnable enabler = new Runnable() { public void run() {
        button.setEnabled(true);
    }};

    private View button;

    public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState) {
        View result = ...
        button = result.findViewById(...);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                button.setEnabled(false);
                ...
            }
        });
        ...
    }

    public void onDestroyView() {
        ...
        button = null;
    }

    public void onPause() {
        ...
        button.removeCallbacks(enabler);
    }

    public void onResume() {
        ...
        button.setEnabled(true);
    }
}

在您的FragmentActivity 消失之前调用removeCallbacks 对于避免用户在禁用期间离开导致的并发问题很重要。在这种情况下禁用回调后,重要的是要确保当用户返回您的FragmentActivity 并且View 恢复其保存状态时,您不会“卡在”禁用状态.

【讨论】:

  • 没关系编辑评论:我忘了改变其他方式!完美运行。我仍然想知道为什么它不适用于我的旧解决方案,但是我想要的只是它可以工作!谢谢。
  • 如果您依赖 if (button_ready) 来避免状态更改,那么问题是 ToggleButtonSwitcher 在内部更改了它们的检查状态:您无法从 @ 中避免这种情况987654332@.
  • 好吧,我相信在 Switch 上调用 enable(false) 会阻止它切换状态!我的意思是我在没有所有周围代码的情况下尝试了它 - 只是用一个禁用它的按钮 - 它有效!
猜你喜欢
  • 2011-11-05
  • 2015-11-15
  • 2012-04-21
  • 2014-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-01
  • 2012-05-08
相关资源
最近更新 更多