2013-05-22 4 views
9

私はバインドされたサービスを持っています。アクティビティがそれをバインドしています。それはアクティビティのサービスonStop()メソッドのバインドを解除します。アクティビティのランタイムが変更されている間にバインドされたサービスが破棄されないようにする方法(例:orientation)

ランタイムの変更(たとえば、方向の変更)がアクティビティに発生すると、アクティビティが再作成されるという問題があります。したがって、onStop()メソッドがアクティビティから呼び出され、そのアクティビティがそのメソッド内のサービスをバインド解除します。その結果、サービスが破棄され、再開されます。

アクティビティが見えなくなったときにサービスを停止したまま、ランタイムの変更でサービスが破棄されないようにしたい。試してみると、startService()が表示されますが、アクティビティが見えなくなってもサービスは停止しません。 stopServiceアクティビティのonStop()を追加すると、結果はbindService()unbindService()と同じになります。

PostDelaying in AcitivityのonStop()では、この問題の一部を解決できますが、遅延時間は任意で、これにより、アクティビティがしばらくの間GCを取得できなくなります。私はより明確な解決策が必要です。

android:configChanges="orientation"のような解決方法は他にもあるので、私はランタイムの変更を処理することをお勧めしません。

つまり、私はサービスがsetRetainInstance(true)と呼ばれる断片のように動作するようにしたいと思います。しかし、フラグメントにはbindService()のようなものはありません。私は何をすべきか?

答えて

9

ただし、フラグメントにはbindService()のようなものはありません。

しかし、彼らはApplicationコンテキストから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でカバー)

、我々は同じを使用することができます結合および結合解除のためのContext。フラグメントを保持することで、構成の変更に対するバインド解除および再バインドを回避できます。

個人的には、私はバインディングパターンを避けようとしています。私は疎結合インターフェイスのファンです。したがって、コマンドパターンとstartService()でサービスを使用する方が好きです。

+0

私はアプリケーションコンテキストを考え出しませんでした。答えてくれてありがとう。 – Naetmul

2

コールのonCreateでSTARTSERVICE、その後onStop

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

これにより、バインドされたサービスが接続をリークさせます。 – Adam

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()では、唯一のサービス状態がリセットされます。

関連する問題