9

私はバインドされたサービスを持っています。アクティビティはそれをバインドしています。Service on Activity のonStop()メソッドのバインドを解除します。

問題は、ランタイムの変更 (向きの変更など) がアクティビティに発生した場合、アクティビティが再作成されることです。したがって、onStop()メソッドはアクティビティから呼び出され、アクティビティはそのメソッドでサービスのバインドを解除します。その結果、サービスが破棄されます (そして再起動されます)。

アクティビティが非表示のときにサービスを停止させたまま、実行時の変更でサービスが破棄されないようにしたい。あなたはそれを試してみると言うことができますがstartService()、アクティビティが見えないときにサービスが停止しないようにします。stopService アクティビティの を追加するonStop()と、結果は および と同じにbindService()なりunbindService()ます。

アクティビティのPostDelayingunbindService()onStop()この問題を部分的に解決できますが、遅延時間は任意になり、アクティビティがしばらくの間 GC を取得できなくなります。もっと明確な解決策が欲しい。

android:configChanges="orientation"他のランタイムの変更もあり、ランタイムの変更を処理するための推奨されない方法であるため、このようなソリューションは必要ありません。

要するに、 Service が を呼び出した Fragment のように動作するようにしたいのですsetRetainInstance(true)。ただし、フラグメントにはbindService(). 私は何をすべきか?

4

3 に答える 3

9

ただし、フラグメントには 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);
  }
}

(このサンプル プロジェクトで見られるように、この本でカバーされています)

Applicationコンテキストを使用することで、バインドとアンバインドに同じものを使用できますContext。フラグメントを保持することで、構成変更時のバインド解除と再バインドを回避できます。

個人的には、バインド パターンを避けようとしています。私は疎結合インターフェースのファンなので、コマンド パターンとstartService().

于 2013-05-22T23:40:41.137 に答える
1

onCreate で startService を呼び出してから onStop を呼び出します

@Override
protected void onStop()
{
    super.onStop();
    if (!isChangingConfigurations ())
    {
          // call stopService
    }
}
于 2013-05-22T23:50:48.187 に答える