【问题标题】:Why does Service destroy self when Activity is destroyed?为什么在Activity被销毁时Service会销毁自己?
【发布时间】:2017-12-24 03:37:23
【问题描述】:

我想从 Activity 启动服务,然后让它继续运行,即使在 Activity 退出/完成时也是如此。然后,当我再次启动应用程序活动时,它会重新附加到现有服务。

我已经阅读了有关 bindService 的文档,但每次我点击后退按钮退出活动时,都会自动调用服务的 onUnBind,从而有效地终止服务。我想我必须在服务解除绑定之前手动调用 unbindService。

我确实知道,一旦 Activity 被销毁,成员变量 mService、mBound 和 tv 必须在新 Activity 创建后重新填充,因此下面的简单代码将显示 "bindService 已启动也就不足为奇了。 " 但我原以为 LocalService 实例中的所有成员变量都是相同的,未更改,因此 "bindService 已经启动。Val = " + mService.myval; 应该保持每次我重新启动一个新活动时都一样,不是吗?

MainActivity

public class MainActivity extends AppCompatActivity
{
    LocalService mService;
    Boolean mBound = false;
    TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv = (TextView)findViewById(R.id.textView);    
    }

    @Override
    protected void onStart()
    {
        super.onStart();
    }

    @Override
    protected void onStop()
    {
        super.onStop();
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
    }

    public void onButtonStart(View v)
    {
        String str;

        // Bind to LocalService
        if (!mBound)
        {
            Intent intent = new Intent(this, LocalService.class);

            if (!bindService(intent, mConnection, Context.BIND_AUTO_CREATE))
            {
                unbindService(mConnection);
                str = "bindService failed?!";
            }
            else
            {
                str = "bindService started.";
            }
        }
        else
            str = "bindService already Started. Val = " + mService.myval;

        tv.setText(str);
    }  

    public void onButtonStop(View v)
    {
        if (mBound)
        {
            mService.stop();
            unbindService(mConnection);
            mBound = false;

            tv.setText("Stopped Service");
        }
        else
            tv.setText("Service is not running");
    }

    private ServiceConnection mConnection = new ServiceConnection()
    {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service)
        {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0)
        {
            mBound = false;
        }
    };   
 }

本地服务

public class LocalService extends Service
{
    private final IBinder mBinder = new LocalBinder();
    private final Random mGenerator = new Random();
    public int myval = getRandomNumber();

    @Override
    public void onCreate()
    {
        super.onCreate();
    }

    // Service is being Destroyed
    @Override
    public void onDestroy()
    {
        super.onDestroy();
    }

    public int getRandomNumber()
    {
        return mGenerator.nextInt(100);
    }

    @Override
    public IBinder onBind(Intent intent)
    {
        return mBinder;
    }

    // Client is Unbinding via the unbindService() call
    @Override
    public boolean onUnbind(Intent intent)
    {
        return super.onUnbind(intent);
    }

    public class LocalBinder extends Binder
    {
        public LocalService getService()
        {
            return LocalService.this;
        }
    }   
}

【问题讨论】:

    标签: android service binding destroy


    【解决方案1】:

    “如果您使用 startService(..) 启动一个 android 服务,该服务将一直运行,直到您明确调用 stopService(..)。系统可以运行服务有两个原因。如果有人调用 Context. startService() 然后系统将检索服务(创建它并在需要时调用其 onCreate() 方法),然后使用客户端提供的参数调用其 onStartCommand(Intent, int, int) 方法。此时服务将继续运行,直到调用 Context.stopService() 或 stopSelf()。请注意,对 Context.startService() 的多次调用不会嵌套(尽管它们确实会导致对 onStartCommand() 的多次相应调用),所以不管它多少次启动后,一旦调用 Context.stopService() 或 stopSelf(),服务就会停止;但是,服务可以使用它们的 stopSelf(int) 方法来确保在处理启动的意图之前服务不会停止。

    客户端还可以使用 Context.bindService() 来获取到服务的持久连接。如果服务尚未运行(在此过程中调用 onCreate()),这同样会创建服务,但不会调用 onStartCommand()。客户端将收到服务从其 onBind(Intent) 方法返回的 IBinder 对象,然后允许客户端调用回服务。只要建立连接,服务就会一直运行(无论客户端是否保留对服务的 IBinder 的引用)。通常返回的 IBinder 是针对用 AIDL 编写的复杂接口。

    服务既可以启动也可以绑定连接。在这种情况下,只要服务已启动或与 Context.BIND_AUTO_CREATE 标志有一个或多个连接,系统就会保持服务运行。一旦这两种情况都不成立,就会调用服务的 onDestroy() 方法并有效地终止服务。从 onDestroy() 返回后,所有清理(停止线程、取消注册接收器)都应完成。”

    【讨论】:

      【解决方案2】:

      我可以看到你正在使用bindService()

      绑定服务通常仅在它为另一个应用程序组件提供服务时才存在,并且不会无限期地在后台运行。

      因此,如果您的 Activity(绑定到服务)已完成,那么服务将不再运行。

      要在后台运行服务,您必须创建带有标志START_STICKYSTICKY 服务。

       @Override
      public int onStartCommand(Intent intent, int flags, int startId) {
        // Do your task here
        return START_STICKY;
       }
      

      START_STICKY 服务可以在没有任何活动的情况下在后台运行。您可以通过回调与服务进行通信。

      要创建 Sticky service ,请阅读 Service

      【讨论】:

      • 我注意到,当我们杀死应用程序并再次调用 onCreate 和 onStartCommand 方法时,服务被破坏了......
      • 不适用于bindService()startService() 就是这种情况。服务可以同时绑定或启动。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      相关资源
      最近更新 更多