Проверьте, активна ли активность
У меня проблема с слушателем в определенной деятельности.
Проблема заключается в том, что этот слушатель содержит alert.show(); который можно вызвать после того, как мы попытаемся нажать новую активность (которая затем дает исключение).
Например: я слушаю активность A для сигнала с другого телефона. Я возвращаюсь назад и пытаюсь запустить новую активность B, но программа вылетает из-за alert.show() прослушивателя.
ERROR/AndroidRuntime(3573): android.view.WindowManager$BadTokenException: Unable to add window -- token [email protected] is not valid; is your activity running?
Можно ли проверить в прослушивателе, активна ли эта активность, а затем показывать предупреждение или нет в зависимости от этого значения?
Ответы
Ответ 1
Может быть, более простой способ я не могу придумать, но один из способов - реализовать его самостоятельно. На onResume()
вы установите переменную-член mIsRunning
в true и на onPause()
обратно на false. Используя это логическое значение, вы должны знать, что не вызываете alert.show()
в ваш обратный вызов.
Ответ 2
ArrayList<String> runningactivities = new ArrayList<String>();
ActivityManager activityManager = (ActivityManager)getBaseContext().getSystemService (Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> services = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (int i1 = 0; i1 < services.size(); i1++) {
runningactivities.add(0,services.get(i1).topActivity.toString());
}
if(runningactivities.contains("ComponentInfo{com.app/com.app.main.MyActivity}")==true){
Toast.makeText(getBaseContext(),"Activity is in foreground, active",1000).show();
alert.show()
}
Таким образом, вы узнаете, является ли указанная активность текущей видимой активностью, иначе ваше предупреждение не будет отображаться.
Это будет работать, когда мы будем перемещаться между двумя действиями без завершения.
Ответ 3
Это происходит, когда Activity будет проходить через его уничтожение, когда фоновый поток завершит свою работу и попытается показать диалог.
Это исключение редко воспроизводится, но происходит, когда мы выполняем операцию async task/background и хотим отобразить диалог с
Контекст активности и в среднем, пока наша деятельность разрушает себя по какой-то причине.
ОС Android должна справиться с этой ситуацией, но на данный момент это не так.
поэтому перед вызовом вашего диалога просто проверьте, запущена ли работа, а не в фазе ее уничтожения.
if(!isFinishing()){
callDialog();
}
Ответ 4
Фоновый поток после завершения сетевых задач вызывает обратный вызов onSuccess()/onFailure() в основном потоке. И если в то время активность, инициировавшая эту задачу фонового потока, не была на переднем плане и вы пытаетесь использовать getActivity() в onSuccess()/onFailure(), это даст вам исключение. Поэтому попробуйте добавить эту проверку перед выполнением каких-либо операций пользовательского интерфейса.
if(!((Activity) context).isFinishing())
{
//show alert
}
Ответ 5
Да, вы можете проверить, активна ли активность: Обновление активности из службы при активном
Кроме того, если вы ничего не делаете, когда ваша активность неактивна, вам, вероятно, следует отменить регистрацию слушателя, когда ваша активность деактивируется.
Ответ 6
У меня было 2 действия A и B, я просто хотел узнать, работает ли операция B или нет.
Изначально я следил за "RunningTaskInfo" для решения проблемы, он не работал на 100%.
Итак, я создал собственное решение, я опубликую свое решение. Использование классов HashMap и AtomicBoolean.
public class ActivityStateTracker {
final private Map<String, AtomicBoolean> mMap = new HashMap<String, AtomicBoolean>();
private static ActivityStateTracker instance = null;
/**
* SingletonClass
* */
private ActivityStateTracker() {
}
public static ActivityStateTracker getInstance(String activityName, boolean defaultVal) {
if(instance == null) {
instance = new ActivityStateTracker();
}
instance.setDefaultValue(activityName, defaultVal);
return instance;
}
private void setDefaultValue(String activityName, boolean defaultVal) {
mMap.put(activityName, new AtomicBoolean(defaultVal));
}
public boolean isRunning(String activityName) {
final AtomicBoolean atomicBool = mMap.get(activityName);
return (mMap.get(activityName) == null) ? false : atomicBool.get();
}
public void setChangeState(String activityName, boolean value) {
final AtomicBoolean atomicBool = mMap.get(activityName);
if(atomicBool == null) {
setDefaultValue(activityName, value);
} else {
atomicBool.set(value);
mMap.put(activityName, atomicBool);
}
}
}
Теперь в действии B.
public static final String TAG = "EditScreenPopupActivity";
static ActivityStateTracker mActivityState = ActivityStateTracker.getInstance(TAG, false);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivityState.setChangeState(TAG, true);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_traslucent);
}
@Override
protected void onDestroy() {
mActivityState.setChangeState(TAG, false);
super.onDestroy();
}
Теперь в действии A.
public static final String TAG = "ToolTipPopupActivity";
static ActivityStateTracker mActivityState = ActivityStateTracker.getInstance(TAG, false);
/** Check Edit screen activity is running or not? */
if(mActivityState.isRunning("EditScreenPopupActivity")) {
finish();
}
......................................
Это решение работает правильно в моем случае.. Я надеюсь, что это тоже поможет вам.
Ответ 7
Для уровня API> = 23 вы можете использовать свойство активности "жизненный цикл" для определения состояния активности. Это дает очень компактный код.
Вот пример кода в Kotlin, как расширение класса:
fun FragmentActivity.isRunning() = lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)
// ...
// Here 'myActivity' can be inherited from different activity-like classes,
// for example, from class AppCompatActivity:
if (myActivity.isRunning()) {
Log.d("log", "Activity is running!")
}