在屏幕方向更改后返回到活动时失去对Android服务的引用

问题描述:

我有一个Activity,它启动并绑定到Service。然后我有另一个Activity,从第一个启动。在从第二个返回到第一个Activity后,我需要调用Service(保存一些数据)的方法。在屏幕方向更改后返回到活动时失去对Android服务的引用

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

当我从离开它时返回到第一个活动的方向不同时,会出现问题。如果发生这种情况,我会失去对Service的引用,因此会在onActivityResult()中遇到NullPointerException。因此,如果我以纵向模式启动我的第二个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(); 
} 

编辑:下面是我的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"); 
} 

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


    } 
+0

您可以发布SMServiceConntection的代码。我期望有一个onServiceConnected()方法,它可以保存活页夹。我使用ServiceConnection的内部类;这样ServiceConnection可以将活页夹保存到活动(包含类)中。 – Stefan 2012-02-17 16:58:27

+0

好吧,我已经添加了代码。 – Spinner 2012-02-17 17:14:55

你的问题可能是,当你返回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)" 
        } 
    } 
    

不要更改清单,以便在方向更改时不重新创建。这是一个丑陋的黑客,没有解决问题,我不喜欢什么时候建议。如果你这样做了,如果其他配置发生了变化,例如语言,或者活动已被框架暂时销毁以节省资源,那么仍会冒同样的风险。

配置清单中的变化只能用于如果您希望获得更改回调而不是重新创建。原因。懒惰不是一个。

+0

谢谢,我已经根据你的第一个建议做了一些事情。我现在有一个私人帮手方法,存储一个请求保存; onServiceConnected()然后检查未决的请求并在必要时执行它。现在发现了一个不同的问题,但是会关闭这个问题。 – Spinner 2012-02-20 13:28:10