gpt4 book ai didi

android - 处理多次按下按钮的最佳实践

转载 作者:行者123 更新时间:2023-11-29 02:04:28 25 4
gpt4 key购买 nike

我发现我的任何应用程序中都有一个常见问题,即用户可能不小心对同一个按钮执行多次点击,从而导致多次执行 onClick 监听器逻辑。通常,我的那些 onClickListeners 的业务逻辑通常包括启动一个执行 HTTP 请求并稍后修改 UI 的繁重进程 AsynTask。

我防止多次执行 asyntask 的方法是在监听器方法开始时禁用按钮,并在 onPostExecute 的第一条语句中再次启用它。这通常对我有用,或者至少我没有收到与这种情况有关的任何问题。

最近,一位同事向我指出了这种无法启用按钮方法的潜在问题。如以下包含两个按钮“+”和“-”的代码所示,快速交替按下这些按钮会导致应用程序因 ArrayOutOfIndex 异常而崩溃。

这个事实让我开始思考我管理 onClickListener 事件并发的方式,以及是否真的有可能在使用上述方法完成第一个异步任务之前启动第二个异步任务的情况.

您对处理这种情况有何建议?

对于那些建议在第一个异步任务完成之前应用一些拒绝第二次启动异步任务的逻辑的建议,是否真的值得将该逻辑普遍应用于按钮执行 http 请求的常用应用程序?

CrashActivity.java

public class CrashActivity extends Activity {

private int mNumbers[] = { 1, 2, 3, 4, 5 };
private int position = 0;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

final TextView result = (TextView) findViewById(R.id.resultTextView);

final Button minusBtn = (Button) findViewById(R.id.minus_button);
final Button plusBtn = (Button) findViewById(R.id.plus_button);

minusBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
minusBtn.setEnabled(false);
plusBtn.setEnabled(true);

result.setText("" + mNumbers[--position]);

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

minusBtn.setEnabled((position > 0));
}
});

plusBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
plusBtn.setEnabled(false);
minusBtn.setEnabled(true);

result.setText("" + mNumbers[position++]);

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
plusBtn.setEnabled((position <= 4));
}
});

minusBtn.setEnabled(false);
}
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<Button
android:id="@+id/minus_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="-" />

<Button
android:id="@+id/plus_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="+" />

<TextView
android:id="@+id/resultTextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="hello stackoverflow!" />

</LinearLayout>

最佳答案

保证两种方法不会同时尝试更新 UI 的解决方案是同步 UI 更新代码。您可以创建一个同步方法或一个 Object 作为代码块的锁。示例:

public synchronized void updateUI() {
// ...
}

private Object mLock = new Object();

public void updateUI() {
// ...
synchronized (mLock) {
// Critical code here.
}
// ...
}

扩展它以确保任务 1 在任务 2 之前完成,在任务 3 之前完成,等等,您需要以某种方式跟踪哪个先开始。注意:在此示例中,同步发生在 UI 线程上。

private List<AsyncTask> mRunningTasks = new ArrayList<AsyncTask>();

public void onClick(View v) {
v.setEnabled(false);
if (v == task1View) {
Task1 task = new Task1();
mRunningTasks.add(task);
task.execute();
}
else if (v == task2View) {
Task2 task = new Task2();
mRunningTasks.add(task);
task.execute();
}
// ...
}

// Copy and paste for each necessary task.
private Task1 extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... v) {
// Run task 1 code here.
while (this != mRunningTasks.get(0)) {
wait(1000);
}
return v[0];
}

protected void onPostExecute(Void v) {
updateUI();
mRunningTasks.remove(0);
task1View.setEnabled(true);
}
}

public void updateUI() {
// UI update code here.
}

关于android - 处理多次按下按钮的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10807254/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com