对 Activity 的弱引用 (Android)

发布于 2024-09-18 14:14:00 字数 1036 浏览 1 评论 0原文

在我的 Android 应用程序中,当用户尝试从一个活动转换到另一个活动时,可能会出现一些全局状态,表明他们需要先完成其他一些操作。

为了实现这一点,我编写了一个包含以下代码的类:

private static WeakReference<Activity> oldActivityReference;
private static Intent waitingIntent;

public static void pushActivity(Activity currentActivity, Intent newActivityIntent) {
    Intent blockingIntent = ThisClass.getBlockingActivity();
    if (blockingIntent != null) {
        ThisClass.oldActivityReference = new WeakReference<Activity>(currentActivity);
        ThisClass.waitingIntent = newActivityIntent;
        currentActivity.startActivity(blockingIntent);
        return;
    }
    currentActivity.startActivity(newActivityIntent);
}

当阻塞活动完成时,它调用 ThisClass.blockingActivityFinished()。这将检查对旧活动的弱引用是否仍然存在,如果存在,则从该活动启动原始意图。如果没有,它将从我的应用程序上下文中启动原始意图。

我的问题是,
这听起来合理吗?这种技术是否存在潜在的内存泄漏问题?有没有更好的方法来实现这一点?

编辑 - 需要明确的是,可能触发中断的事件类型包括 1) 表明当前应用程序版本已弃用的服务器 ping 2) 表明用户凭据不再有效的任何服务器 RPC。我不想向每个活动添加逻辑来处理这些活动的检查,并在完成后恢复正常业务。这违反了 DRY,并且在团队环境中容易出错。

In my Android app, when a user tries to transition from one activity to another, there may be some global state that indicates they need to complete some other action first.

To accomplish this, I've written a class with the following code:

private static WeakReference<Activity> oldActivityReference;
private static Intent waitingIntent;

public static void pushActivity(Activity currentActivity, Intent newActivityIntent) {
    Intent blockingIntent = ThisClass.getBlockingActivity();
    if (blockingIntent != null) {
        ThisClass.oldActivityReference = new WeakReference<Activity>(currentActivity);
        ThisClass.waitingIntent = newActivityIntent;
        currentActivity.startActivity(blockingIntent);
        return;
    }
    currentActivity.startActivity(newActivityIntent);
}

When the blocking activity finishes, it calls ThisClass.blockingActivityFinished(). That will check to see if the weak reference to the old activity still exists and, if so, launch the original intent from that activity. If not, it will launch the original intent from my application's context.

My question is,
Does this sound sane? Are there any potential memory leak issues with this technique? Is there a better way to accomplish this?

EDIT -
To be clear, the types of events that might trigger an interruption are 1) a server ping indicating that the current app version is deprecated 2) any server RPC indicating that the user's credentials are no longer valid. I do not want to add logic to every Activity to handle checking for these, and resuming business as usual once they complete. That is a violation of DRY, and error-prone in a team environment.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

童话里做英雄 2024-09-25 14:14:00

这听起来合理吗?

我永远不会使用这种技术。尽管如此,可变静态数据成员仍然是危险的。特别是,如果用户做了不可想象的事情,例如将他们的手机用作电话,或者以其他方式长时间离开您的应用程序流程,我预计此操作会失败。您的活动可能会被销毁并且您的进程可能会终止以释放 RAM,但活动将保留在任务中并可能会重新激活。到那时,你的状态就会很糟糕,因为静电被摧毁了。

此技术是否存在任何潜在的内存泄漏问题?

您正在泄漏Intent

有没有更好的方法来实现这一点?

出于本答案其余部分的目的,我将把您的起点称为活动 A,将“其他操作”称为活动 B,将所需的结束称为活动 C。因此,在您的代码中,newActivityIntent 用于 Activity C,blockingIntent 用于 Activity B,currentActivity 用于 Activity A。

选项 #1:将决策过程放在 Activity C 中,而不是活动 A。让活动 C 检查 onCreate() 中的条件,如果条件要求显示活动 B,则立即调用活动 B 的 startActivity()

选项#2:将决策过程留在活动 A 中,但在 Intent extra 中传递布尔值(例如,“我们必须显示活动 B”的 true)活动 C 的 startActivity() 调用。活动 C 检查 onCreate() 中的布尔值,并立即调用活动 B 的 startActivity()(如果布尔值是这么说的。

在这些选项中,您可以避免静态。

Does this sound sane?

I'd never use this technique. Mutable static data members are dangerous, WeakReference notwithstanding. In particular, I'd expect this to fail if the user does the unthinkable and, say, uses their phone as a phone, or otherwise leaves your application flow for an extended period of time. Your activities may be destroyed and your process terminated to free up RAM, yet the activities would remain in the task and might be reactivated. At that point, your state is whack, because the statics got nuked.

Are there any potential memory leak issues with this technique?

You're leaking an Intent.

Is there a better way to accomplish this?

For the purposes of the rest of this answer, I'm going to refer to your starting point as Activity A, the "some other action" as Activity B, and the desired end as Activity C. So, in your code, newActivityIntent is for Activity C, blockingIntent is for Activity B, and currentActivity is Activity A.

Option #1: Put the decision-making process in Activity C, rather than Activity A. Have Activity C check the condition in onCreate() and immediately calls startActivity() for Activity B if the conditions require Activity B to be shown.

Option #2: Leave the decision-making process in Activity A, but pass the boolean (e.g., true for "we gotta show Activity B") in an Intent extra for the startActivity() call for Activity C. Activity C checks the boolean in onCreate() and immediately calls startActivity() for Activity B if the boolean says so.

In these options, you avoid the statics.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文