如何防止在Activity的运行时更改时销毁绑定的Service(例如:orientation)

时间:2013-05-22 23:23:07

标签: java android android-service

我有一个绑定的服务。活动正在绑定它。它取消绑定服务的活动onStop()方法。

问题是,如果Activity发生了运行时更改(例如,方向更改),则会重新创建Activity。因此,从Activity调用onStop()方法,并且Activity在该方法中取消绑定服务,这会导致服务的破坏(并重新启动它)。

我希望保持Service不会在运行时更改中被销毁,同时在Activity不可见时保持Service停止。您可以说尝试startService()但是当Activity不可见时,它会使服务停止。如果我添加stopService Activity onStop(),则结果与bindService()unbindService()相同。

在Acitivity unbindService()中推迟onStop()可以部分解决此问题,但延迟时间将是任意的,这会阻止Activity在一段时间内获得GC。我想要一个更清晰的解决方案。

我不想要像android:configChanges="orientation"这样的解决方案,因为还有其他运行时更改,并且这是处理运行时更改的不鼓励方式。

简而言之,我希望服务就像一个名为setRetainInstance(true)的片段。但是,碎片没有bindService()之类的东西。我该怎么办?

3 个答案:

答案 0 :(得分:9)

  

但是,Fragments没有类似bindService()的东西。

但他们可以使用bindService()上下文中的Application

public class BshFragment extends Fragment implements OnClickListener,
    ServiceConnection {
  private IScript service=null;
  private Button btn=null;

  public View onCreateView(LayoutInflater inflater,
                           ViewGroup container,
                           Bundle savedInstanceState) {
    View result=inflater.inflate(R.layout.main, container, false);

    btn=(Button)result.findViewById(R.id.eval);
    btn.setOnClickListener(this);
    btn.setEnabled(false);

    setRetainInstance(true);

    return(result);
  }

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    getActivity().getApplicationContext()
                 .bindService(new Intent(getActivity(),
                                         BshService.class), this,
                              Context.BIND_AUTO_CREATE);
  }

  @Override
  public void onDestroy() {
    getActivity().getApplicationContext().unbindService(this);
    disconnect();

    super.onDestroy();
  }

  @Override
  public void onClick(View view) {
    EditText script=(EditText)getView().findViewById(R.id.script);
    String src=script.getText().toString();

    service.executeScript(src);
  }

  @Override
  public void onServiceConnected(ComponentName className, IBinder binder) {
    service=(IScript)binder;
    btn.setEnabled(true);
  }

  @Override
  public void onServiceDisconnected(ComponentName className) {
    disconnect();
  }

  private void disconnect() {
    service=null;
    btn.setEnabled(false);
  }
}

(见this sample project中所见,this book

通过使用Application上下文,我们可以使用相同的Context进行绑定和解除绑定。通过保留片段,我们可以避免在配置更改时解除绑定和重新绑定。

就个人而言,我只是试图避免绑定模式。我是松散耦合接口的粉丝,所以我更喜欢通过命令模式和startService()使用服务。

答案 1 :(得分:2)

在onCreate中调用startService,然后在onStop上调用

@Override
protected void onStop()
{
    super.onStop();
    if (!isChangingConfigurations ())
    {
          // call stopService
    }
}

答案 2 :(得分:0)

在运行时更改期间保持活动唯一绑定服务的另一种方法是在服务类中定义类似keepAlive的方法:

public void keepAlive(boolean value) {
    if (value) startService(new Intent(getApplicationContext(), getClass()));
    else stopSelf();
}

@Override
public void onRebind(Intent intent) {
    keepAlive(false);
}

@Override
public boolean onUnbind(Intent intent) {
    return true;
}

onRebind()中,重置了唯一绑定的服务状态。