0

我有一个 android (4.1) 应用程序,据报道(无法重新创建)出现消息“应用程序已停止”。然而,问题是用户必须在弹出的警报中按“确定”。仅当应用程序未处于活动状态(在屏幕上)时才会发生碰撞。这表明 Android 由于内存或调皮而杀死了我的应用程序。我一直在调查内存泄漏,因为我在应用程序中处理位图,但没有得到回报。

我有一个捕获并记录所有默认处理程序,如下所示:

Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
            public void uncaughtException(Thread thread, Throwable ex) {
                Log.e(StaticData.LogTag, "Unhandled exception app", ex);
            }
        });

记录所有异常。之后我调用原始异常处理程序。这个处理程序放在应用程序主活动上。当“停止”的 chrash 发生时,永远不会调用该方法,但在其他情况下会调用该方法。

我的应用程序使用 IntentService 在后台将数据发送到服务器。这不是一个长时间运行的服务,1-10 秒。我也会尝试在服务上放置一个默认的异常处理程序。我提到该服务是因为该应用程序在“屏幕外”时被终止,所以我认为这可能与问题有关,但原因逃避了我。

此外,我使用 BroadcastReceiver 来通知应用程序有关网络连接更改的主要活动,因为该应用程序是在动荡的网络条件下使用的。这是相关的,因为当人们谈论可能的内存泄漏问题时,我看到 BroadcastReceiver 被提及。我的 BradcastReceiver 实现如下:

服务端:

sendOrderedBroadcast(uploadedIntent, null);

活动方面:

public static class NetworkStateReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent in) {
        // super.onReceive(context, intent);
        Log.d(StaticData.LogTag, "Network connectivity change");
        if (in.getExtras() != null) {
            NetworkInfo ni = (NetworkInfo) in.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
            if (ni != null && ni.getState() == NetworkInfo.State.CONNECTED) {
                Log.i(StaticData.LogTag, "Network " + ni.getTypeName() + " connected");
                ...                 
            }
        }
        if (in.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE)) {
            Log.d(StaticData.LogTag, "There's no network connectivity");
        }
    }
}

正如我在开头提到的,这个问题主要是对用户的烦恼,因为他在查看邮件或接听电话时必须在弹出窗口上按确定。该应用程序足够强大,可以处理它不时被杀死的情况,但是,我想弄清楚为什么我的应用程序被淘汰了。

PS。我试图让用户通过 mx log logcollector 发送错误报告,但没有雪茄。

4

1 回答 1

0

我似乎已经解决了这个问题。我认为罪魁祸首是对应用程序中主要活动的静态引用。我正在使用这个静态来获取对应用程序上下文的引用。然而,这在 Service 和 BroadcastReceiver 中是不必要的,因为它们有自己对“上下文”的引用。

为什么不开心?

对 Android 视图(如 Activity)的静态引用保存在内存中,不能被垃圾收集器释放。这就是使其成为静态的想法。我想将来引用该对象,但这是错误的方法。

当改变方向(例如)时,Android 重新创建当前活动(和子视图),并且旧的被释放用于 GC。当您有一个视图的静态引用时,它不会被收集,现在您有 2 个 Activity 实例。算算一下,这显然会随着时间的推移而填满内存(泄漏),Android 会在某个时候破坏应用程序。

当面对这个问题时,你必须意识到你必须将你的数据/状态转移到新的 Activity 中,例如通过使用共享内存、本地数据库或 savedInstanceState:

@Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
       int value = savedInstanceState.getInteger("key");
    }
}
@Override
protected void onSaveInstanceState(final Bundle outState) {
    outState.putInteger("key", value);
}
于 2013-10-24T12:45:51.263 回答