屏幕方向更改后返回“活动”时丢失对Android服务的引用

Spi*_*ner 5 android screen-orientation android-service android-activity

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

在查看每种屏幕时,只要退出之前我返回相同的屏幕方向Activity,我的Activity生命周期方法似乎就足以应对屏幕方向的更改Activity

当我以离开我的方向不同的方式返回到第一个活动时,就会发生问题。如果发生这种情况,我将失去对自己的引用Service,因此会遇到NullPointerExceptionin onActivityResult()。因此,如果我Activity在人像模式下启动第二个,在查看第二个时切换到风景,而在风景模式下Activity返回第一个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();
}
Run Code Online (Sandbox Code Playgroud)

编辑:这是我的SMServiceConnection类的摘录,它是我的Activity中的一个私有内部类,该类从自定义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");
}
Run Code Online (Sandbox Code Playgroud)

我的ServiceConnection超类是这样的:

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;
    }


    }
Run Code Online (Sandbox Code Playgroud)

Seb*_*son 4

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

我会尝试以下两件事之一:

  1. 尝试将数据保存为待处理信息:

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

    然后稍后再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)"
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

正如您所说,您不应该更改清单,以免在方向更改时重新创建。这是一个丑陋的黑客,不能解决问题,我不喜欢这样的建议。如果您这样做,如果其他配置发生更改(例如语言)或者活动已被框架暂时销毁以节省资源,您仍然面临发生同样情况的风险。

仅当您想要获取更改的回调而不是重新创建时,才必须使用清单中的 configchanges。原因。懒惰不是其中之一。