Android:开关(切换按钮)和线程
在我针对安卓4.0.3的应用程序中,我曾经有一个按钮用作开关。单击按钮正在进行资源更改(在播放/暂停之间切换),一些任务正在后台执行。特殊之处在于,当按下按钮时,我希望切换在短时间内不可用(以防止快速切换) 为此,我创建了一个等待X秒的线程,如下所示:Android:开关(切换按钮)和线程,android,multithreading,layout,button,toggle,Android,Multithreading,Layout,Button,Toggle,在我针对安卓4.0.3的应用程序中,我曾经有一个按钮用作开关。单击按钮正在进行资源更改(在播放/暂停之间切换),一些任务正在后台执行。特殊之处在于,当按下按钮时,我希望切换在短时间内不可用(以防止快速切换) 为此,我创建了一个等待X秒的线程,如下所示: void blockButton(){ new Thread() { public void run(){ try { synchronized(th
void blockButton(){
new Thread() {
public void run(){
try {
synchronized(this){
button_ready = false;
sleep(5000);
button_ready = true;
}
}
catch(InterruptedException ex){}
}
}.start();
}
}
基本上是在我的活动中
if(button_ready){
// Start background stuff
changeButtonResource();
button.setEnabled(false);
blockButton();
button.setEnabled(true);
}
到目前为止一切都很顺利。但我最终还是想把它更新成一个开关。代码基本相同(除了变成OnCheckedChangeListener的onClickListener)
但是现在,当我单击一次按钮时,再次单击它将允许更改其资源-但是后台任务不会启动(我已经用可控震源和其他工具尝试过了,它只会更改资源)
因此,我几乎有我的按钮过去的行为,但资源变得一团糟。任何想法都是非常受欢迎的!谢谢。您不需要创建其他线程
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);
}
}
在
片段
或活动
消失之前调用removeCallbacks
,对于避免用户在禁用期间离开而导致并发问题非常重要。在这种情况下禁用回调后,当用户返回到片段
或活动
并且视图
恢复其保存状态时,确保您不会“卡在”禁用状态非常重要。您不需要创建另一个线程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);
}
}
在
片段
或活动
消失之前调用removeCallbacks
,对于避免用户在禁用期间离开而导致并发问题非常重要。在这种情况下禁用回调后,当用户返回到片段
或活动
并且视图
恢复其保存状态时,确保您不会“卡在”禁用状态非常重要。您的同步块不会做任何事情(this
引用的线程是一个局部变量,因此不共享。)button\u ready
是如何声明的?volatile
?button\u ready是类中的一个正则变量,在onCreate()方法中初始化。同样,该方法与一个简单的按钮一起工作非常好,因此线程可以做一些事情(change var,wait,change var)。要使代码线程安全(这可能解决问题,也可能无法解决问题):删除同步块并将变量声明为volatile:private volatile boolean button_ready;
。感谢您的提示(尽管没有解决问题),您的同步块没有做任何事情(this
引用的线程是一个局部变量,因此不共享。)button\u ready
是如何声明的?volatile
?button\u ready是类中的一个正则变量,在onCreate()方法中初始化。同样,该方法与一个简单的按钮一起工作非常好,因此线程可以做一些事情(change var,wait,change var)。要使代码线程安全(这可能解决问题,也可能无法解决问题):删除同步块并将变量声明为volatile:private volatile boolean button\u ready;
。感谢您的提示(尽管没有解决问题)nevermind编辑的评论:我忘了改变另一种方式!效果很好。我仍然想知道为什么它不能与我的旧解决方案一起工作,但嘿,我只想让它工作!谢谢。如果你依赖你的If(按钮准备就绪)
为了避免状态更改,问题是切换按钮和切换器在内部更改其选中状态:您无法从OnClickListener
中避免这种情况。我相信调用enable(false)是正确的在开关上会阻止它切换状态!我的意思是,我在没有使用所有周围代码的情况下尝试了它-只使用了一个禁用它的按钮-它成功了!无需编辑注释:我忘了改变另一种方式!工作得很好。我仍然想知道为什么它不能与我的旧解决方案一起工作,但嘿,我只想让它工作!谢谢。我如果您依靠if(button_ready)
来避免状态更改,问题是ToggleButton
和Switcher
在内部更改其选中状态:您无法通过OnClickListener
来避免这种情况。我相信调用enable(false)打开开关会阻止它切换状态!我的意思是,我在没有使用所有周围代码的情况下尝试了它-只使用了一个禁用它的按钮-它成功了!