如何在按下button时防止活动加载两次

我想弄清楚的是,如果我按下button两次,防止活动加载两次。

我有一个点击button加载的活动,说

myButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { //Load another activity } }); 

现在,因为要加载的活动与web服务和其他操作有关,所以加载需要一些时间。 当然,我有一个加载视图。 但在此之前,如果我按下button两次,我可以看到两次加载的活动。

有谁知道如何防止这个?

在button的事件监听器中,禁用button并显示另一个活动。

  Button b = (Button) view; b.setEnabled(false); Intent i = new Intent(this, AnotherActitivty.class); startActivity(i); 

覆盖onResume()重新启用button。

 @Override protected void onResume() { super.onResume(); Button button1 = (Button) findViewById(R.id.button1); button1.setEnabled(true); } 

将其添加到Androidmanifest.xmlActivity定义中

 android:launchMode = "singleInstance" 

你可以像这样使用意向标志。

 Intent intent = new Intent(Class.class); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); activity.startActivity(intent); 

在历史堆栈的顶部只能打开一个活动。

假设@wannik是正确的,但如果我们有超过1个button调用相同的动作监听器,我几乎在同一时间点击两个button开始下一个活动之前…

所以这是好的,如果你有场private boolean mIsClicked = false; 并在听众:

 if(!mIsClicked) { mIsClicked = true; Intent i = new Intent(this, AnotherActitivty.class); startActivity(i); } 

onResume()我们需要返回状态:

 @Override protected void onResume() { super.onResume(); mIsClicked = false; } 

我和@ wannik的答案之间有什么差别?

如果在其调用视图的侦听器中将enabled设置为false,则仍将启用使用相同侦听器的其他button。 所以为了确保监听者的动作不被调用两次,你需要有一个全局的东西来禁用所有的监听者的调用(如果是新实例或者不是,

我的答案和其他答案有什么不同?

他们正在思考正确的方式,但他们没有考虑将来返回到调用活动的同一个实例:)

希望这可以帮助:

  protected static final int DELAY_TIME = 100; // to prevent double click issue, disable button after click and enable it after 100ms protected Handler mClickHandler = new Handler() { public void handleMessage(Message msg) { findViewById(msg.what).setClickable(true); super.handleMessage(msg); } }; @Override public void onClick(View v) { int id = v.getId(); v.setClickable(false); mClickHandler.sendEmptyMessageDelayed(id, DELAY_TIME); // startActivity() }` 

我认为你会以错误的方式解决问题。 一般来说,一个活动在任何启动生命周期方法( onCreate()onResume()等等)中进行长时间的Web请求是一个坏主意。 真的,这些方法应该只是用来实例化和初始化你的活动将使用的对象,因此应该相对较快。

如果您需要执行Web请求,请在新启动的活动的后台线程中执行此操作(并在新活动中显示加载对话框)。 一旦后台请求线程完成,它可以更新活动并隐藏对话框。

这意味着您的新活动应立即启动并防止双击。

使用singleInstance来避免活动调用两次。

 <activity android:name=".MainActivity" android:label="@string/activity" android:launchMode = "singleInstance" /> 

其他非常非常简单的解决scheme,如果你不想使用onActivityResult()是禁用button2秒(或你想要的时间),是不是很理想,但可以部分解决问题是一些情况下,代码很简单:

  final Button btn = ... btn.setOnClickListener(new OnClickListener() { public void onClick(View v) { //start activity here... btn.setEnabled(false); //disable button //post a message to run in UI Thread after a delay in milliseconds btn.postDelayed(new Runnable() { public void run() { btn.setEnabled(true); //enable button again } },1000); //1 second in this case... } }); 

既然SO不允许我评论其他答案,我必须用一个新的答案来污染这个线程。

“活动打开两次”问题和我对这些解决scheme的经验(Android 7.1.1)的常见答案:

  1. 禁用button,启动活动:工作,但感觉有点笨拙。 如果您有多种方式来启动应用程序中的活动(例如,在操作栏中的button以及通过单击列表视图中的项目),则必须跟踪多个GUI元素的启用/禁用状态。 另外,例如,禁用列表视图中的单击项目并不是很方便。 所以,不是一个非常普遍的方法。
  2. launchMode =“singleInstance”:不使用startActivityForResult(),使用startActivity()取消导航,不build议Android清单文档的常规应用程序。
  3. launchMode =“singleTask”:不适用于startActivityForResult(),不build议Android清单文档的常规应用程序。
  4. FLAG_ACTIVITY_REORDER_TO_FRONT:中断返回button。
  5. FLAG_ACTIVITY_SINGLE_TOP:不工作,活动仍然打开两次。
  6. FLAG_ACTIVITY_CLEAR_TOP:这是唯一为我工作的人。

编辑:这是用startActivity()开始的活动。 当使用startActivityForResult()我需要设置FLAG_ACTIVITY_SINGLE_TOP和FLAG_ACTIVITY_CLEAR_TOP。

只需在buttononClick方法中维护一个标志为:

public boolean oneTimeLoadActivity = false;

  myButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if(!oneTimeLoadActivity){ //start your new activity. oneTimeLoadActivity = true; } } }); 

如果你使用onActivityResult,你可以使用一个variables来保存状态。

 private Boolean activityOpenInProgress = false; myButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if( activityOpenInProgress ) return; activityOpenInProgress = true; //Load another activity with startActivityForResult with required request code } }); protected void onActivityResult(int requestCode, int resultCode, Intent data) { if( requestCode == thatYouSentToOpenActivity ){ activityOpenInProgress = false; } } 

在后退button上工作也是因为请求代码在事件上返回。

对于这种情况,我将singleTask在manifest.xml或者Activity的onResume()onDestroy()方法中使用两个接近的singleTask中的一个。

对于第一个解决scheme:我喜欢在清单中使用singleTask而不是singleInstance ,因为使用singleInstance我发现在某些情况下,活动为自己创build一个新的独立实例,导致在两个单独的应用程序窗口在bcakground运行的应用程序,除了额外的内存分配,这将导致非常糟糕的用户体验,当用户打开应用程序视图select一些应用程序恢复。 因此,更好的方法是在manifest.xml中定义如下所示的活动:

 <activity android:name=".MainActivity" android:launchMode="singleTask"</activity> 

你可以在这里查看活动启动模式。


对于第二种解决scheme,您只需定义一个静态variables或一个首选variables,例如:

 public class MainActivity extends Activity{ public static boolean isRunning = false; @Override public void onResume() { super.onResume(); // now the activity is running isRunning = true; } @Override public void onDestroy() { super.onDestroy(); // now the activity will be available again isRunning = false; } } 

另一方面,当你想发起这个活动,只需检查:

 private void launchMainActivity(){ if(MainActivity.isRunning) return; Intent intent = new Intent(ThisActivity.this, MainActivity.class); startActivity(intent); } 

这只是为我工作时startActivity(intent)

 intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); 
 myButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { myButton.setOnClickListener(null); } }); 

使用一个flagvariables将其设置to true ,检查它是否真正只是return其他执行活动调用。

你也可以使用setClickable(false)来执行Activity Call

 flg=false public void onClick(View view) { if(flg==true) return; else { flg=true; // perform click} } 

你也可以试试这个

 Button game = (Button) findViewById(R.id.games); game.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent myIntent = new Intent(view.getContext(), Games.class); startActivityForResult(myIntent, 0); } }); 

你可以重写startActivityForResult并使用实例variables:

 boolean couldStartActivity = false; @Override protected void onResume() { super.onResume(); couldStartActivity = true; } @Override public void startActivityForResult(Intent intent, int requestCode, Bundle options) { if (couldStartActivity) { couldStartActivity = false; intent.putExtra(RequestCodeKey, requestCode); super.startActivityForResult(intent, requestCode, options); } }