Android点击通知时按条件跳转Activity的实现问题
问题分析与解决方案
你的问题出在用静态变量ActivityB.instance判断当前页面是否处于前台的方式不可靠,而且这种写法还容易导致内存泄漏。当应用进程被系统回收或者ActivityB已经被销毁时,这个静态变量可能并没有被置为null,导致你的else分支永远不会执行;反过来,就算应用在后台,只要这个变量没被回收,判断逻辑也会出错。
下面是正确的实现思路和代码:
1. 用应用生命周期回调跟踪前台Activity
我们可以通过自定义Application类,注册ActivityLifecycleCallbacks来准确跟踪当前处于前台的Activity,这样就能可靠判断是否是ActivityB在前台。
自定义Application类
public class MyApp extends Application { private static MyApp instance; private Activity currentForegroundActivity; @Override public void onCreate() { super.onCreate(); instance = this; // 注册Activity生命周期回调 registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {} @Override public void onActivityStarted(@NonNull Activity activity) {} @Override public void onActivityResumed(@NonNull Activity activity) { // 记录当前处于前台的Activity currentForegroundActivity = activity; } @Override public void onActivityPaused(@NonNull Activity activity) { // 当前Activity退到后台时清空记录 if (currentForegroundActivity == activity) { currentForegroundActivity = null; } } @Override public void onActivityStopped(@NonNull Activity activity) {} @Override public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {} @Override public void onActivityDestroyed(@NonNull Activity activity) {} }); } public static MyApp getInstance() { return instance; } // 判断当前是否是ActivityB在前台 public boolean isActivityBInForeground() { return currentForegroundActivity != null && currentForegroundActivity instanceof ActivityB; } }
记得在AndroidManifest.xml中注册这个Application:
<application android:name=".MyApp" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyApp"> <!-- 你的Activity注册 --> </application>
2. 修改BroadcastReceiver的判断逻辑
现在我们可以用Application中提供的可靠判断方法来替换原来的静态变量判断:
@Override public void onReceive(Context context, Intent intent) { Log.e("NotificationReceiver","NotificationReceiver"); MyApp myApp = MyApp.getInstance(); // 如果不是ActivityB在前台,就打开ActivityA if (!myApp.isActivityBInForeground()) { Intent i = new Intent(context, ActivityA.class); // 添加FLAG_ACTIVITY_NEW_TASK确保在非Activity环境下能启动 // 添加FLAG_ACTIVITY_CLEAR_TOP确保如果A已经存在,清空栈顶回到A i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); context.startActivity(i); } // 如果是ActivityB在前台,什么都不做 }
额外提醒
- 永远不要用静态变量持有Activity实例,这会导致Activity无法被GC回收,引发严重的内存泄漏问题。
FLAG_ACTIVITY_CLEAR_TOP的作用是:如果ActivityA已经在任务栈中存在,那么会把栈中A上面的所有Activity销毁,直接回到A,这符合登录页的使用场景(用户从通知回到登录页时,不需要保留之前的栈)。
内容的提问来源于stack exchange,提问作者pAr
相关产品推荐
相关产品推荐

