我有一个基于计时器的启动屏幕。我的问题是在调用 finish()
方法之前,我需要检查下一个活动是否已经启动,因为系统会弹出一个对话框,我只想在用户选择对话框选项后才调用 finish()
方法。
我知道有很多问题是关于如何判断活动是否在前台运行,但我不确定这是否适用于位于活动顶部的对话框。
这是问题所在,红色表示我的活动在后台,而对话框在前台:
编辑: 我尝试过不使用 finish()
方法,但是这样我的活动会在应用程序栈中被保留,我要避免这种情况发生。
我有一个基于计时器的启动屏幕。我的问题是在调用 finish()
方法之前,我需要检查下一个活动是否已经启动,因为系统会弹出一个对话框,我只想在用户选择对话框选项后才调用 finish()
方法。
我知道有很多问题是关于如何判断活动是否在前台运行,但我不确定这是否适用于位于活动顶部的对话框。
这是问题所在,红色表示我的活动在后台,而对话框在前台:
编辑: 我尝试过不使用 finish()
方法,但是这样我的活动会在应用程序栈中被保留,我要避免这种情况发生。
你尝试过不调用finish方法,并在清单文件中添加android:noHistory="true"吗?这样可以防止该活动进入堆栈。
我必须说,你的工作流不符合标准的Android方式。在Android中,如果你想通过Intent打开另一个Activity,你不需要调用finish()
方法关闭当前的Activity。为了方便用户,在Android中可以使用“返回键”从你打开的Activity返回到你的应用程序。
因此,只需要让系统停止你的Activity并保存需要保存的内容,当你的Activity被重新调用时就会自动恢复。
既然你明确要求了一个Activity,我在我的Utils类中添加了一个简单的静态方法,通过传递该activity来获取activity的状态。
public static boolean isActivityVisible(Activity mActivity) {
if (mActivity != null) {
Class klass = mActivity.getClass();
while (klass != null) {
try {
Field field = klass.getDeclaredField("mResumed");
field.setAccessible(true);
Object obj = field.get(mActivity);
return (Boolean)obj;
} catch (NoSuchFieldException exception1) {
Log.e(TAG, exception1.toString());
} catch (IllegalAccessException exception2) {
Log.e(TAG, exception2.toString());
}
klass = klass.getSuperclass();
}
}
return false;
}
在Activity
内部使用这些方法。
isDestroyed()
添加于Api 17
如果最终的onDestroy()调用已经在Activity上执行,那么返回true,即该实例现在已经失效。
isFinishing()
添加于Api 1
检查此活动是否正在完成过程中,无论是因为您在其上调用了finish()还是因为其他人请求其完成。这通常在onPause()中使用,以确定活动是仅暂停还是彻底完成。
来自内存泄漏文档
AsyncTask
的一个常见错误是捕获对主机 Activity
(或 Fragment
)的强引用:
class MyActivity extends Activity {
private AsyncTask<Void, Void, Void> myTask = new AsyncTask<Void, Void, Void>() {
// Don't do this! Inner classes implicitly keep a pointer to their
// parent, which in this case is the Activity!
}
}
AsyncTask
很容易比父Activity
更长久,例如当任务正在运行时发生配置更改。static
类,它不会捕获父级,并持有对主机Activity
的弱引用。class MyActivity extends Activity {
static class MyTask extends AsyncTask<Void, Void, Void> {
// Weak references will still allow the Activity to be garbage-collected
private final WeakReference<MyActivity> weakActivity;
MyTask(MyActivity myActivity) {
this.weakActivity = new WeakReference<>(myActivity);
}
@Override
public Void doInBackground(Void... params) {
// do async stuff here
}
@Override
public void onPostExecute(Void result) {
// Re-acquire a strong reference to the activity, and verify
// that it still exists and is active.
MyActivity activity = weakActivity.get();
if (activity == null
|| activity.isFinishing()
|| activity.isDestroyed()) {
// activity is no longer valid, don't do anything!
return;
}
// The activity is still valid, do main-thread stuff here
}
}
}
public class startMenuActivity extends AppCompatActivity {
// other code snippets here
// ...................
boolean isAppInBackground;
@Override
protected void onCreate(Bundle SaveInstanceState) {
super.onCreate(SaveInstanceState);
setContentView(layout.start_menu);
isAppInBackground =
((myApp)this.getApplication()).getIsAppInBackground();
if (!isAppInBackground) {
showCCPAConsentDialog();
}
// other code snippets here
// ...................
}
@Override
protected void onStop() {
Log.d("ACTIVITYSTAT", "StartMenuActivity is in the background");
((myApp)this.getApplication()).setIsAppInBackground(true);
super.onStop();
}
@Override
protected void onResume() {
Log.d("ACTIVITYSTAT", "StartMenuActivity is in the foreground");
/* code snippet for your global variable to indicate that your
app activity is in the foreground */
super.onResume();
}
}
我以前的做法是,
如果活动不在前台
getIntent()
将返回 null。:=P