当Activity被销毁时,为什么Service会破坏自我?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当Activity被销毁时,为什么Service会破坏自我?相关的知识,希望对你有一定的参考价值。

我想从一个Activity启动一个服务,然后让它继续运行,即使活动退出/结束。然后,当我再次启动应用程序活动时,它会重新连接到现有服务。

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

我不知道,一旦Activity被销毁,成员变量mService,mBound和tv必须在创建新Activity时重新填充,所以下面的简单代码将显示“bindService started”并不奇怪。但我认为LocalService实例中的所有成员变量都是相同的,没有变化,所以“bindService已经开始.Val =”+ mService.myval;每次重新启动一项新活动应该保持不变,不是吗?

主要信息

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;
        }
    }   
}
答案

“如果你用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标志有一个或多个连接,系统就会保持服务运行。一旦这些情况都不成立,就会调用Service的onDestroy()方法并有效终止服务。从onDestroy()返回时,应完成所有清理(停止线程,取消注册接收器)。“

另一答案

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

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

因此,如果您的活动(绑定到服务)已完成,则服务将不再运行。

要在后台运行服务,您必须使用标志STICKY创建START_STICKY服务。

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

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

为了创建一个Sticky service阅读Service

以上是关于当Activity被销毁时,为什么Service会破坏自我?的主要内容,如果未能解决你的问题,请参考以下文章

Android activity和service的生命周期对比

service

3.4 重新创建 Activity

线程会不会随着activity的结束而结束?

android service 自动解绑并销毁

android中启动service的activity销毁了,这时怎么关闭service?