버튼을 누를 때 활동이 두 번로드되는 것을 방지하는 방법
첫 번째 클릭 후 즉시 버튼을 두 번 누르면 활동이 두 번로드되는 것을 방지하려고합니다.
버튼 클릭시로드되는 활동이 있습니다.
myButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
//Load another activity
}
});
이제로드 할 활동에 네트워크 호출이 있기 때문에로드하는 데 약간의 시간이 걸립니다 (MVC). 이것에 대한 로딩 뷰를 보여 주지만 그 전에 버튼을 두 번 누르면 액티비티가 두 번로드되는 것을 볼 수 있습니다.
아무도 이것을 방지하는 방법을 알고 있습니까?
버튼의 이벤트 리스너에서 버튼을 비활성화하고 다른 활동을 표시합니다.
Button b = (Button) view;
b.setEnabled(false);
Intent i = new Intent(this, AnotherActitivty.class);
startActivity(i);
onResume()
버튼을 다시 활성화하려면 재정의 합니다.
@Override
protected void onResume() {
super.onResume();
Button button1 = (Button) findViewById(R.id.button1);
button1.setEnabled(true);
}
이것을 Activity
정의에 추가하십시오 AndroidManifest.xml
...
android:launchMode = "singleTop"
이와 같은 인 텐트 플래그를 사용할 수 있습니다.
Intent intent = new Intent(Class.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
activity.startActivity(intent);
기록 스택의 맨 위에 하나의 활동 만 열리게됩니다.
SO는 다른 답변에 대해 댓글을 달 수 없기 때문에이 스레드를 새로운 답변으로 오염시켜야합니다.
'활동이 두 번 열립니다'문제에 대한 일반적인 답변과이 솔루션에 대한 내 경험 (Android 7.1.1) :
- 활동을 시작하는 버튼 비활성화 : 작동하지만 약간 서투른 느낌입니다. 앱에서 활동을 시작하는 여러 방법이있는 경우 (예 : 작업 표시 줄의 버튼 및 목록보기에서 항목 클릭) 여러 GUI 요소의 활성화 / 비활성화 상태를 추적해야합니다. 예를 들어 목록보기에서 클릭 한 항목을 비활성화하는 것은 그리 편리하지 않습니다. 따라서 매우 보편적 인 접근 방식은 아닙니다.
- launchMode = "singleInstance": startActivityForResult ()와 함께 작동하지 않고 startActivity ()를 사용하여 탐색을 중단합니다. Android 매니페스트 문서의 일반 애플리케이션에는 권장되지 않습니다.
- launchMode = "singleTask": startActivityForResult ()에서 작동하지 않습니다. Android 매니페스트 문서의 일반 애플리케이션에는 권장되지 않습니다.
- FLAG_ACTIVITY_REORDER_TO_FRONT : 뒤로 버튼을 끊습니다.
- FLAG_ACTIVITY_SINGLE_TOP : 작동하지 않고 활동이 여전히 두 번 열립니다.
- FLAG_ACTIVITY_CLEAR_TOP : 이것은 나를 위해 일하는 유일한 사람입니다.
편집 : 이것은 startActivity ()로 활동을 시작하기위한 것입니다. startActivityForResult ()를 사용할 때 FLAG_ACTIVITY_SINGLE_TOP 및 FLAG_ACTIVITY_CLEAR_TOP를 모두 설정해야합니다.
@wannik이 옳다고 가정 해 보겠습니다.하지만 동일한 액션 리스너를 호출하는 버튼이 2 개 이상이고 다음 활동을 시작하기 전에 거의 동시에 두 개의 버튼을 클릭하면 ...
따라서 필드 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로 설정하면 동일한 리스너를 사용하는 다른 버튼이 계속 활성화됩니다. 따라서 리스너의 액션이 두 번 호출되지 않도록하려면 리스너의 모든 호출을 비활성화하는 전역적인 것이 필요합니다 (새 인스턴스인지 여부는 신경 쓰지 마십시오)
내 답변과 다른 답변의 차이점은 무엇입니까?
그들은 올바른 방식으로 생각하고 있지만 호출 활동의 동일한 인스턴스로의 향후 복귀를 생각하지 않습니다. :)
그것은 나를 위해 일했을 때만 startActivity(intent)
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
두 번 호출하는 활동을 피하려면 singleInstance를 사용하십시오.
<activity
android:name=".MainActivity"
android:label="@string/activity"
android:launchMode = "singleInstance" />
나는 당신이 문제를 잘못된 방법으로 해결하려고한다고 생각합니다. 일반적으로는 활동이 시작 라이프 사이클 방법 (의에서 장기 실행 웹 요청을해야 할 나쁜 생각 onCreate()
, onResume()
등). 실제로 이러한 메서드는 활동에서 사용할 개체를 인스턴스화하고 초기화하는 데 사용되어야하며 따라서 상대적으로 빠릅니다.
웹 요청을 수행해야하는 경우 새로 시작된 활동의 백그라운드 스레드에서이 작업을 수행하고 새 활동에서로드 대화 상자를 표시합니다. 백그라운드 요청 스레드가 완료되면 활동을 업데이트하고 대화 상자를 숨길 수 있습니다.
그러면 새 활동이 즉시 시작되고 더블 클릭이 가능하지 않게됩니다.
도움이 되었기를 바랍니다:
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()
}`
사용하지 않으려 onActivityResult()
는 다른 매우 간단한 솔루션 은 2 초 (또는 원하는 시간) 동안 버튼을 비활성화하는 것입니다. 이상적이지는 않지만 일부 경우 문제를 해결할 수 있으며 코드는 간단합니다.
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...
}
});
이 상황에서는 singleTask
manifest.xml에서 접근 한 두 가지 중 하나 또는 Activity의 onResume()
& onDestroy()
메소드에서 각각 플래그를 사용합니다 .
를 들어 첫 번째 솔루션 : 내가 사용하는 것을 선호 singleTask
보다는 매니페스트의 활동을 위해 singleInstance
사용에 따라, singleInstance
나는 어떤 경우에 활동이 실행중인 앱에서 두 개의 별도의 응용 프로그램 창을 가지고 결과 자체에 대한 새로운 별도의 인스턴스를 생성하는 것을 알아 냈 bcakground에 추가 메모리 할당 외에 사용자가 앱보기를 열어 재개 할 일부 앱을 선택할 때 매우 나쁜 사용자 경험을 초래할 수 있습니다. 따라서 더 나은 방법은 다음과 같이 manifest.xml에서 활동을 정의하는 것입니다.
<activity
android:name=".MainActivity"
android:launchMode="singleTask"</activity>
들어 두 번째 솔루션, 당신은 예를 들어, 정적 변수 또는 환경 변수를 정의 할 수 있습니다 :
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);
}
버튼 onClick 메소드에서 다음과 같이 하나의 플래그를 유지하십시오.
공개 부울 oneTimeLoadActivity = false;
myButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if(!oneTimeLoadActivity){
//start your new activity.
oneTimeLoadActivity = true;
}
}
});
onActivityResult를 사용하는 경우 변수를 사용하여 상태를 저장할 수 있습니다.
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;
}
}
이벤트에서 요청 코드가 반환되기 때문에 뒤로 버튼을 눌렀을 때도 작동합니다.
myButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myButton.setOnClickListener(null);
}
});
flag
변수를 사용하여 설정 to true
하고 참인지 확인 return
하고 활동 호출을 수행하십시오.
활동 호출을 실행하는 setClickable (false)을 사용할 수도 있습니다.
flg=false
public void onClick(View view) {
if(flg==true)
return;
else
{ flg=true;
// perform click}
}
startActivityForResult를 재정의하고 인스턴스 변수를 사용할 수 있습니다.
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);
}
}
// 이벤트 시간을 추적하는 변수
private long mLastClickTime = 0;
2. onClick에서 현재 시간과 마지막 클릭 시간 차이가 i 초 미만이면 아무것도하지 마십시오 (반환) 그렇지 않으면 클릭 이벤트로 이동하십시오.
@Override
public void onClick(View v) {
// Preventing multiple clicks, using threshold of 1 second
if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) {
return;
}
mLastClickTime = SystemClock.elapsedRealtime();
// Handle button clicks
if (v == R.id.imageView2) {
// Do ur stuff.
}
else if (v == R.id.imageView2) {
// Do ur stuff.
}
}
}
당신은 또한 이것을 시도 할 수 있습니다
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);
}
});
'code' 카테고리의 다른 글
iOS White to Transparent Gradient Layer is Gray (0) | 2020.10.13 |
---|---|
jQuery Chosen 재설정 (0) | 2020.10.13 |
MySQL-이 버전의 MySQL은 아직 'LIMIT & IN / ALL / ANY / SOME 하위 쿼리를 지원하지 않습니다. (0) | 2020.10.13 |
가로 스크롤 만 사용하는 Div (0) | 2020.10.13 |
ImageMagick 설치 확인 (0) | 2020.10.13 |