2017-10-24 5 views
0

내 앱에 Timer이 무한히 실행되어 Animation입니다. 같은 : 사용자가 앱을 사용하지 않는 경우 Android 타이머 종료

Timer t = new Timer(); 
t.scheduleAtFixedRate(new TimerTask() { 

    @Override 
    public void run() { 
     runOnUiThread(new Runnable() { 

      @Override 
      public void run() { 
       //Running Animation Code 
      } 
     }); 
    } 
}, 1000, 1000); 

는 지금은 사용자가 안드로이드의 Back Button을 클릭하는 경우에도이 코드가 실행되는 것을 깨달았다. 사실 그것은 백그라운드에서 실행되며 그것은 많은 메모리를 사용하는 것 같습니다.

이 코드를 실행하려면 ONLY if user in the app이 필요합니다. 사용자가 Back Button을 클릭하면이 Timer이 끝나고 사용자가 Home Button을 클릭하면 잠시 후 사용자가 앱을 사용하지 않으면이 Timer이 종료됩니다.

내가 필요한 것은 메모리 사용을 막는 것입니다. 이 코드가 잠시 실행되면 깨달았 기 때문에 앱이 정지됩니다! 나는 정상적인 행동이 필요하다.

답변

0

ActivityBackStack의 마지막 요소 인 경우 버튼을 눌렀을 때처럼 백그라운드에 놓입니다.

이와 같이, onPause() 메소드가 트리거됩니다.

따라서 애니메이션을 취소 할 수 있습니다.

@Override protected void onPause() { 
    this.timer.cancel(); 
} 

onResume() 방법으로 애니메이션을 시작해야합니다. onCreate() 바로 뒤에 onResume()이 호출됩니다. 따라서 추운 앱 시작에서 애니메이션을 시작하는 것이 적합합니다. 앱 (: 벨소리 선택기 예컨대)에서 다른 응용 프로그램을 시작하면

@Override protected void onResume() { 
    this.timer.scheduleAtFixedRate(...); 
} 

onPause()도 호출됩니다. 마찬가지로 앱으로 돌아 가면 onResume()이 실행됩니다.


onBackPressed()에 같은 코드 줄을 추가 할 필요가 없습니다.

onStop() 또는 onDestroy()에서 애니메이션을 중지 할 때의 요점은 무엇입니까?

onPause()에서 이미 수행하십시오. 앱이 백그라운드로 들어가면 애니메이션은 이미 취소되며 은 많은 메모리를 사용하지 않습니다.

왜 내가 복잡한 대답을 보는지 모르겠다.

0

onBackPressed() 또는 onDestroy()에 상관없이 원하는대로 할 수 있습니다. 당신이 필요로하는 경우

if (t != null) { 
    t.cancel(); 
} 

, 당신이 onResume()에 타이머를 시작하고 onStop() 그것을 취소 할 수 있습니다, 그것은 완전히 당신의 요구 사항에 따라 달라집니다.

호출자가 타이머 작업 실행 스레드 을 빠르게 종료하려는 경우 호출자는 타이머의 cancel 메서드를 호출해야합니다. 이이 작업을 수행 할 수있는 100 % 최선의 방법이 될하지 않을 수 있습니다 그리고 그것은 일부에 의해 나쁜 사례로 간주 될 수 있습니다 - Android Timer documentation

또한 purgeHow to stop the Timer in android?

0

면책 조항을 볼 수 있습니다.

프로덕션 응용 프로그램에서 아래 코드를 사용했으며 작동합니다. 그러나 나는 당신에게 아주 좋은 시작을 제공해야하는 기본 샘플로 그것을 (특정 애플 리케이션 참조 및 코드를 제거) 편집했습니다.

정적 변수 mIsAppVisible 변수는 앱에서 어디에서나 호출 할 수 있으므로 (앱에서 App 클래스를 통해) 앱이 포커스/가시성이 있어야하는 조건에 따라 코드가 실행되어야하는지 확인합니다. 또한,


public class App extends Application { 
    public static boolean mIsAppVisible = false; 


    ... 
} 

는 "부모"활동을 만들기 클래스 등의 응용 프로그램이 실제로 상호 작용 있는지 ParentActivity을 확장하여 활동에 mIsAppInBackground을 확인하는 수

모든 다른 활동들도 확장됩니다.

public class ParentActivity extends Activity { 
    public static boolean mIsBackPressed = false; 
    public static boolean mIsAppInBackground = false; 
    private static boolean mIsWindowFocused = false; 
    public boolean mFailed = false; 
    private boolean mWasScreenOn = true; 

    @Override 
    protected void onStart() { 
     applicationWillEnterForeground(); 

     super.onStart(); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 

     applicationDidEnterBackground(); 
    } 

    @Override 
    public void finish() { 
     super.finish(); 

     // If something calls "finish()" it needs to behave similarly to 
     // pressing the back button to "close" an activity. 
     mIsBackPressed = true; 
    } 

    @Override 
    public void onWindowFocusChanged(boolean hasFocus) { 
     mIsWindowFocused = hasFocus; 

     if (mIsBackPressed && !hasFocus) { 
      mIsBackPressed = false; 
      mIsWindowFocused = true; 
     } 

     if (!mIsWindowFocused && mFailed) 
      applicationDidEnterBackground(); 

     if (isScreenOn() && App.mIsAppVisible && hasFocus) { 
      // App is back in focus. Do something here... 

      // this can occur when the notification shade is 
      // pulled down and hidden again, for example. 
     } 

     super.onWindowFocusChanged(hasFocus); 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 

     if (!mWasScreenOn && mIsWindowFocused) 
      onWindowFocusChanged(true); 
    } 

    @Override 
    public void onBackPressed() { 
     // this is for any "sub" activities that you might have 
     if (!(this instanceof MainActivity)) 
      mIsBackPressed = true; 

     if (isTaskRoot()) { 
      // If we are "closing" the app 
      App.mIsAppVisible = false; 
      super.onBackPressed(); 
     } else 
      super.onBackPressed(); 
    } 

    private void applicationWillEnterForeground() { 
     if (mIsAppInBackground) { 
      mIsAppInBackground = false; 
      App.mIsAppVisible = true; 

      // App is back in foreground. Do something here... 

      // this happens when the app was backgrounded and is 
      // now returning 
     } else 
      mFailed = false; 
    } 

    private void applicationDidEnterBackground() { 
     if (!mIsWindowFocused || !isScreenOn()) { 
      mIsAppInBackground = true; 
      App.mIsAppVisible = false; 

      mFailed = false; 

      // App is not in focus. Do something here... 
     } else if (!mFailed) 
      mFailed = true; 
    } 

    private boolean isScreenOn() { 
     boolean screenState = false; 
     try { 
      PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); 

      screenState = powerManager.isInteractive(); 
     } catch (Exception e) { 
      Log.e(TAG, "isScreenOn", e); 
     } 

     mWasScreenOn = screenState; 

     return screenState; 
    } 
} 
당신이 당신의 활동에 방법을 만들 수 있습니다 귀하의 사용 (코드는 MainActivity 가정) 즉 penguin이 제안 t.cancel(); 메소드를 호출 할 수있는 애니메이션을 처리에 대한

.

if (this instanceof MainActivity) { 
    ((MainActivity) this).cancelTimer(); 
} 

을 아니면 ParentActivity 클래스에 타이머를 추가 한 다음 instanceof 검사 또는 별도의 방법이 필요 없습니다 : 그런 다음 ParentActivity.applicationDidEnterBackground() 방법에 다음을 추가 할 수 있습니다.