android - 屏幕方向更改后返回 Activity 时丢失对 Android 服务的引用

标签 android android-service screen-orientation android-activity

我有一个启动并绑定(bind)到 ServiceActivity。然后我有另一个 Activity,从第一个开始。从第二个返回到第一个 Activity 后,我需要调用 Service 的一个方法(保存一些数据)。

在查看每个 Activity 时,我的 Activity 生命周期方法似乎可以充分应对屏幕方向的变化,前提是我在退出 Activity 之前返回到相同的屏幕方向

当我以与离开时不同的方向返回到第一个 Activity 时,就会出现问题。如果发生这种情况,我将失去对我的 Service 的引用,并因此在 onActivityResult() 中遇到 NullPointerException。因此,如果我以纵向模式启动第二个 Activity,在查看第二个 Activity 时切换到横向,然后以横向模式返回到第一个 Activity ,它会崩溃。

我可能遗漏了什么?我不想使用 list 文件来指示我将处理配置更改——我觉得这是一个有点丑陋的 hack,它没有解决主要问题。除非我又遗漏了什么...

以下是第一个 Activity 的生命周期方法的摘录:

@Override
protected void onStart()
{
super.onStart();

// start and bind to service
startService(smsIntent);
connection = new SMServiceConnection();
bindService(smsIntent, connection, Context.BIND_AUTO_CREATE);

}

@Override
protected void onRestart()
{
super.onRestart();
}

@Override
protected void onResume()
{
super.onResume();
}

@Override
protected void onPause()
{
super.onPause();
sms.save(); // autosave
}

@Override
protected void onStop()
{
super.onStop();
unbindService(connection);
// stopService(smsIntent); //doesn't appear to have any effect
}

@Override
protected void onDestroy()
{
super.onDestroy();
}

编辑:这是我的 SMServiceConnection 类的摘录,它是我的 Activity 中的私有(private)内部类,它从自定义 ServiceConnection 类扩展而来。

@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
    super.onServiceConnected(name, service);
    msg("Service connected");
    sms = getSMService();
    if (sms != null)
    {
    String s = sms.getStuff(); //etc.; haven't listed every method invoked on sms

        sms.saveSurvey();
    }
    } else
    {
    System.out.println("sms is null!");
    }

}

@Override
public void onServiceDisconnected(ComponentName name)
{
    super.onServiceDisconnected(name);
    msg("Service disconnected");
}

我的 ServiceConnection 父类(super class)类似于:

public class MyServiceConnection implements ServiceConnection
{
    private boolean serviceAvailable = false;
    private SMService sms;

    public void onServiceConnected(ComponentName name, IBinder service)
    {
        serviceAvailable = true;
        LocalBinder b = (LocalBinder) service;
        sms = b.getService();
    }

    public void onServiceDisconnected(ComponentName name)
    {
        serviceAvailable = false;
    }

    public boolean isServiceAvailable()
    {
    return serviceAvailable;
    }

    public SMService getSMService()
    {
    return sms;
    }


    }

最佳答案

您的问题可能是在您返回时再次绑定(bind)服务之前调用了 onActivityResult(),这发生在 onstart 中的 bindcall 之后。

我会尝试以下两种方法之一:

  1. 尝试将数据保存为未决信息:

    if (sms == null) {
        mPendingResultCode = resultCode;
        mPedingResultData = new Bundle(intent.getExtras()); } else {
        handleData(resultCode, intent.getExtras()); }
    

    然后在 onServiceConnected 调用 handleData(mPedingResultCode, mPedingResultData) 如果例如 mPendingResultData != null

    并确保取消设置 mPendingResultCode 和 mPendingResultData 或者 完成数据后的一些其他指标。

  2. 我不确定这一点,但也许会尝试通过在 onActivityResult 中执行以下操作将数据处理添加到事件队列的后面:

    final Bundle data = new Bundle(intent.getExtras);
    new Handler().postRunnable(new Runnable() {
        public void run() {
            "do some stuff with data and resultcode (which should be final in the parameter list anyway)"
        }
    }
    

正如您所说,您不应该更改 list 以在方向更改时不重新创建。这是一个丑陋的 hack,不能解决问题,我不喜欢这样的建议。如果您这样做,如果某些其他配置(例如语言)发生更改,或者如果 Activity 已被框架暂时销毁以节省资源,您仍然有可能发生同样的事情。

list 中的 configchanges 必须仅在您想要获得更改的回调而不是重新创建时使用。原因。懒惰不是其中之一。

关于android - 屏幕方向更改后返回 Activity 时丢失对 Android 服务的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9332187/

相关文章:

android - 如何检测我的 Activity 何时被遮挡?

android - 如何在没有 'onLocationChange' 方法的情况下知道 GPS 位置

应用程序内的 android 远程服务与单独的应用程序

Android – 监听传入的 SMS 消息

ios - 按下后退按钮时更改界面方向

android - 预训练的 keras 模型在 android 中返回相同的结果

android - SQLite 添加列,保留数据

android - onStart() 和 onStartCommand() 仍然在 2.0 及更高版本中调用

android - REVERSE_PORTRAIT 检测不到?

android - 横向启动 Android 模拟器