code

버튼을 누를 때 활동이 두 번로드되는 것을 방지하는 방법

codestyles 2020. 10. 13. 07:50
반응형

버튼을 누를 때 활동이 두 번로드되는 것을 방지하는 방법


첫 번째 클릭 후 즉시 버튼을 두 번 누르면 활동이 두 번로드되는 것을 방지하려고합니다.

버튼 클릭시로드되는 활동이 있습니다.

 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) :

  1. 활동을 시작하는 버튼 비활성화 : 작동하지만 약간 서투른 느낌입니다. 앱에서 활동을 시작하는 여러 방법이있는 경우 (예 : 작업 표시 줄의 버튼 및 목록보기에서 항목 클릭) 여러 GUI 요소의 활성화 / 비활성화 상태를 추적해야합니다. 예를 들어 목록보기에서 클릭 한 항목을 비활성화하는 것은 그리 편리하지 않습니다. 따라서 매우 보편적 인 접근 방식은 아닙니다.
  2. launchMode = "singleInstance": startActivityForResult ()와 함께 작동하지 않고 startActivity ()를 사용하여 탐색을 중단합니다. Android 매니페스트 문서의 일반 애플리케이션에는 권장되지 않습니다.
  3. launchMode = "singleTask": startActivityForResult ()에서 작동하지 않습니다. Android 매니페스트 문서의 일반 애플리케이션에는 권장되지 않습니다.
  4. FLAG_ACTIVITY_REORDER_TO_FRONT : 뒤로 버튼을 끊습니다.
  5. FLAG_ACTIVITY_SINGLE_TOP : 작동하지 않고 활동이 여전히 두 번 열립니다.
  6. 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...
        }
    });

이 상황에서는 singleTaskmanifest.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);
            }

        });

참고URL : https://stackoverflow.com/questions/8077728/how-to-prevent-the-activity-from-loading-twice-on-pressing-the-button

반응형