2013-06-17 12 views
33

Tôi đã đi qua các tài liệu dịch vụ trong android khi tôi nhận thấy hai điểm mâu thuẫn:Khi nào Dịch vụ bắt đầu và bị ràng buộc bị hủy?

Trong các dịch vụ tài liệu đó được quy định tại Managing the Lifecycle of a Service

Hai con đường không hoàn toàn riêng biệt. Tức là, bạn có thể liên kết với dịch vụ đã được bắt đầu với startService(). Ví dụ: một dịch vụ nhạc nền có thể được bắt đầu bằng cách gọi startService() với mục đích xác định nhạc để phát. Sau đó, có thể khi người dùng muốn thực hiện kiểm soát đối với người chơi hoặc nhận thông tin về bài hát hiện tại, một hoạt động có thể liên kết với dịch vụ bằng cách gọi bindService(). Trong các trường hợp như thế này, stopService() hoặc stopSelf() không thực sự ngừng dịch vụ cho đến khi tất cả khách hàng unbind.

Nhưng trong tài liệu về các dịch vụ ràng buộc trong Managing the Lifecycle of a Bound Service

Tuy nhiên, nếu bạn chọn để thực hiện các phương pháp onStartCommand() gọi lại , sau đó bạn phải dừng lại một cách rõ ràng các dịch vụ, vì dịch vụ tại là được coi là bắt đầu. Trong trường hợp này, dịch vụ chạy cho đến khi dịch vụ tự dừng lại với stopSelf() hoặc một thành phần khác gọi stopService(), bất kể nó có bị ràng buộc với bất kỳ khách hàng nào không.

Nó có thể là tôi nhưng tôi nghĩ rằng những điều khoản được contradictory.Could ai vui lòng làm rõ ...

Trả lời

42

Trên thực tế, cả hai đoạn bổ sung cho nhau (mặc dù cách diễn đạt của họ có thể lạc lối), và cả hai đoạn văn phù hợp với hình ảnh từ tài liệu. Chúng ta hãy xem:

Hai đường dẫn này không hoàn toàn tách biệt. Tức là, bạn có thể liên kết với một dịch vụ đã được bắt đầu với startService(). Ví dụ, một dịch vụ nhạc nền có thể được bắt đầu bằng cách gọi startService() với một Intent xác định âm nhạc để phát. Sau đó, có thể khi người dùng muốn thực hiện kiểm soát đối với người chơi hoặc nhận thông tin về bài hát hiện tại, một hoạt động có thể liên kết với dịch vụ bằng cách gọi bindService(). Trong trường hợp như thế này, stopService() hoặc stopSelf() không thực sự dừng dịch vụ cho đến khi tất cả các máy khách không được liên kết.

Tinh hoa là: Nếu bạn bắt đầu dịch vụ, sau đó liên kết khách hàng với dịch vụ, sau đó cố gắng dừng dịch vụ, dịch vụ sẽ không bị ngừng (bị hủy) trước khi tất cả khách hàng hủy liên kết. Đoạn thứ hai không mâu thuẫn, nó tinh chỉnh tuyên bố này.

Tuy nhiên, nếu bạn chọn triển khai phương thức gọi lại onStartCommand(), thì bạn phải ngừng dịch vụ một cách rõ ràng, vì dịch vụ hiện được coi là bắt đầu. Trong trường hợp này, dịch vụ sẽ chạy cho đến khi dịch vụ tự dừng với stopSelf() hoặc thành phần khác gọi stopService(), bất kể nó có bị ràng buộc với bất kỳ máy khách nào không.

Điều này có nghĩa là: Dịch vụ bắt đầu và bị ràng buộc chạy ngay cả khi không có khách hàng nào bị ràng buộc cho đến khi dừng hẳn.Cấp, từ ngữ có thể có một chút rõ ràng hơn về điều này. Sơ đồ vòng đời được đưa ra trong tài liệu hướng dẫn tuy nhiên cho thấy điều này (và tôi chắc rằng tôi đã quan sát này trong "đời thực", mặc dù tôi hiện không có ví dụ trực tiếp trên đỉnh đầu của tôi):

Lifecycle for started and bound services

+0

Giải thích tuyệt vời ... cảm ơn vì đã xóa nó .. – anz

+0

Vì vậy, giả sử tôi muốn unbind và ngừng một dịch vụ đã được bắt đầu và bị ràng buộc, tôi nên gọi stopService sau khi trước khi unbinding nó? Hoặc nó không quan trọng? –

+0

Nó không quan trọng trong thứ tự bạn làm điều đó. Dịch vụ sẽ không bị phá hủy trước khi không phải tất cả khách hàng đều không liên kết và nó đã bị dừng lại (như bạn có thể thấy trong câu trả lời của @ChuckKrutsinger). – Stephan

51

Đồng ý rằng tài liệu có thể rõ ràng hơn. Những gì họ đang cố gắng để nói là:

  • Nếu bạn gọi startService(), sau đó dịch vụ sẽ tiếp tục chạy trừ khi và cho đến khi bạn gọi stopSerivce() (hoặc stopSelf() từ bên trong dịch vụ)
  • Nếu bạn call bindService(), sau đó dịch vụ sẽ tiếp tục chạy trừ khi và cho đến khi bạn gọi unbindService()
  • Do đó, nếu bạn gọi cả startService() và bindService(), thì dịch vụ sẽ tiếp tục chạy cho đến khi bạn gọi cả stopService và unbindService (). Không tự mình sẽ ngừng dịch vụ.

Tạo một hoạt động và dịch vụ rất đơn giản và chạy các chuỗi sau đây của start/stop/bind/unbind. Tôi quan sát thấy rằng các cuộc gọi đã cho kết quả sau.

bind-unbind

bindService() caused: 
    onCreate() 
    onBind() 
unbindService() caused: 
    onUnbind() 
    onDestroy() 

khởi bind-unbind ngừng

startService() caused: 
    onCreate() 
    onStartCommand() 
bindService() caused: 
    onBind() 
unbindService() caused: 
    onUnbind() 
stopService() caused: 
    onDestroy() 

khởi bind-stop-unbind

startService() caused: 
    onCreate() 
    onStartCommand() 
bindService() caused: 
    onBind() 
stopService() caused: 
    -- nothing 
unbindService() caused: 
    onUnbind() 
    onDestroy() 

bind-start-stop-unbind

bindService() caused: 
    onCreate() 
    onBind() 
startService() caused: 
    onStartCommand() 
stopService() caused: 
    -- nothing -- still running 
unbindService() caused: 
    onUnbind() 
    onDestroy() 

bind-start-unbind ngừng

bindService() caused: 
    onCreate() 
    onBind() 
startService() caused: 
    onStartCommand() 
unbindService() caused: 
    onUnbind() 
stopService() caused: 
    onDestroy() 

Như bạn có thể thấy, trong mỗi trường hợp mà cả hai ràng buộc và bắt đầu được gọi, dịch vụ tiếp tục chạy cho đến khi cả hai unbind và stop được gọi. Trình tự của unbind/stop không quan trọng.

Đây là đoạn mã ví dụ mà được gọi từ nút riêng biệt trong ứng dụng thử nghiệm đơn giản của tôi:

public void onBindBtnClick(View view) { 
    Intent intent = new Intent(MainActivity.this, ExampleService.class); 
    bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); 
} 

public void onUnbindBtnClick(View view) { 
    if (serviceIsBound) { 
     unbindService(serviceConnection); 
     serviceIsBound = false; 
    } 
} 

public void onStartBtnClick(View view) { 
    Intent intent = new Intent(MainActivity.this, ExampleService.class); 
    startService(intent); 
} 

public void onStopBtnClick(View view) { 
    Intent intent = new Intent(MainActivity.this, ExampleService.class); 
    exampleService.stopService(intent); 
} 
+5

Cảm ơn các nghiên cứu đã đưa vào đây – anz

+0

Giải thích tuyệt vời ... đã giúp ích rất nhiều ... cảm ơn – John

+0

Giải thích rõ ràng nhất cho đến nay. Điều này sẽ có sẵn trong tài liệu. Làm tốt lắm! –

1

Yep, nó hoạt động. Tôi muốn hoàn thành với mã mẫu:

Tôi phải tạo một ứng dụng có dịch vụ bắt đầu bằng hoạt động, hoạt động phải gọi một số phương thức trong dịch vụ, dịch vụ phải chạy ở chế độ nền ngay cả khi hoạt động đã bị giết và khi hoạt động khởi động lại, nó không phải khởi động lại dịch vụ nếu nó đang chạy. Tôi hy vọng nó sẽ giúp bạn, bạn có thể thấy nó hoạt động như thế nào với Log. Vì vậy, đó là mã số:

public class MyActivity extends Activity{ 

    private MyService myService; 
    private boolean mIsBound = false; 

    private ServiceConnection mConnection = new ServiceConnection() { 

     public void onServiceConnected(ComponentName className, IBinder binder) { 
      MyService.MyBinder b = (MyService.MyBinder) binder; 
      myService = b.getService(); 
      mIsBound = true 
      //Do something 
      // Here you can call : myService.aFonctionInMyService(); 

     } 
     public void onServiceDisconnected(ComponentName className) { 
      // Do something 
      mIsBound = false; 
     } 
    } 



    protected void onCreate(Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     super.onCreate(savedInstanceState); 

     //Checked if my service is running 
     if (!isMyServiceRunning()) { 
      //if not, I start it. 
      startService(new Intent(this,MyService.class)); 
     } 
    } 

    private boolean isMyServiceRunning() { 
     ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 
     for (RunningServiceInfo service : manager 
       .getRunningServices(Integer.MAX_VALUE)) { 
      if (MyService.class.getName().equals(
        service.service.getClassName())) { 
       return true; 
      } 
     } 
     return false; 
    } 

    @Override 
    protected void onResume() { 
     // TODO Auto-generated method stub 
     super.onResume(); 
     doBindService(); 
    } 




    //Connection to the Service 
    private void doBindService() { 
     bindService(new Intent(this,MyService.class), mConnection, 
       Context.BIND_AUTO_CREATE); 
    } 

    // Disconnection from the service 
    private void doUnbindService() { 
     if (mIsBound) { 
      // Detach our existing connection. 
      unbindService(mConnection); 
     } 
    } 

    @Override 
    protected void onPause() { 
     // TODO Auto-generated method stub 
     doUnbindService(); 
     super.onPause(); 
    } 

} 


public class MyService extends Service{ 


    public static String Tag = "MyService"; 
    private final IBinder mBinder = new MyBinder(); 

    @Override 
    public void onCreate() { 
     // TODO Auto-generated method stub  
     super.onCreate(); 
     Log.d(Tag, "onCreate()"); 

    } 

    public class MyBinder extends Binder { 
     public LocationService getService() { 
      return LocationService.this; 
     } 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     // TODO Auto-generated method stub 
     Log.d(Tag, "onBind()"); 
     return mBinder; 
    } 

    @Override 
    public boolean onUnbind(Intent intent) { 
     // TODO Auto-generated method stub 
     Log.d(Tag, "onUnBind()"); 
     return super.onUnbind(intent); 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     // TODO Auto-generated method stub 
     Log.d(Tag,"onStartCommand()"); 

     return START_STICKY; 
    } 

    @Override 
    public void onDestroy() { 
     // TODO Auto-generated method stub 

     Log.d(Tag, "onDestroy"); 
     super.onDestroy(); 
    } 

    public void aFonctionInMyService(){ 
     //Do Something 
    } 

} 
+0

isMyServiceRunning chậm và đưa nó vào hoạt động onCreate() là hoạt động không tốt – Simon