Android service解析与使用实例

最近又学习了下service,对service又多了一些了解和认识。温故而知新,这话果然没错,现在趁热打铁,赶紧记下来。

  • service定义:
    Service是android四大组件之一,主要用于在后台处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态。而Service是运行在主线程里的,如果直接在Service中处理一些耗时的逻辑,就会导致程序ANR,所以需要另外开启子线程来处理。

  • 基本用法:
    新建MyService继承自Service;
    在MainActivity中启动和停止Service代码如下:
    Intent startservice = new Intent(this, MyService.class);
    startService(startservice);//启动
    Intent stopIntent = new Intent(this, MyService.class);
    stopService(stopIntent); //停止

    不要忘了在AndroidManifest.xml中注册
    MyService Service启动后如果没有StopService操作即使activity被销毁任然会在后台运行

  • Service和activity通信:
    任何一个Service在整个应用程序范围内可以和任何一个Activity(通信)建立关联
    Start service 和 Stop service相对应
    Bind service 和unbind service相对应,在activity中是成对出现
    启动并绑定service后,想销毁service,必须有停止和解绑两个执行操作,单独某一个都不能销毁service
    *注意 当activity与service绑定后退出activity或销毁activity后activity与service绑定关系解除,可能程序还会报错,所以有必要在activity的onDestory()方法内调用unbindService()解除绑定

    下面是简单的测试service生命周期代码:
    service类代码:
    类中包含一继承service就必须实现的onBind()和重写了的onCreate()、 onStartCommand() 、onStart()、onDestroy()方法。activity与service就是通过onBind()来进行连接,具体操作看下面代码。

    注意看方法中的注释、Log和I的赋值

public class MyService extends Service {
    public static final String TAG = "MyService";
    public int I = 0;
   /*activity与service绑定时会调用*/
    public IBinder onBind(Intent intent) {
        I = 10;
        Log.e(TAG, "ooo----------onBind()     " + "       getI==" + I);
        return new MyBinder();
    }

    /*第一次创建时才会调用,之后在服务没被销毁都不会调用 ,创建*/
    public void onCreate() {
        super.onCreate();
        I = 1;
        Log.e(TAG, "ooo----------onCreate()     " + "       getI==" + I);
    }

    /*第一次创建时和以后每次启动都会调用,重建*/
    public int onStartCommand(Intent intent, int flags, int startId) {
        I = 2;
        Log.e(TAG, "ooo----------onStartCommand()      " + "getI==" + I);
      // Log.e(TAG, "eee----------onStartCommand()      "+intent+"     " + "getI=="+I +"    "+ flags +"第"+startId+"次启动");

        return super.onStartCommand(intent, flags, startId);

    }

   /*和onStartCommand()方法一样每次都会调用,启动*/
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        I=3;
        Log.e(TAG, "ooo----------onStart()      " + "getI==" + I);
    }

    /*销毁时调用*/
    public void onDestroy() {
        super.onDestroy();
        I = 4;
        Log.e(TAG, "ooo----------onDestroy()    " + "       getI==" + I);

    }

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

    public int getI() {
        return I;
    }
}

布局文件servict_layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <Button
        android:id="@+id/service_start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="启动" />

    <Button
        android:id="@+id/service_stop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="停止" />

    <Button
        android:id="@+id/service_bind"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="绑定" />

    <Button
        android:id="@+id/service_unbind"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="解除" />
  <Button
        android:id="@+id/show_oclick_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="getI" />

    <TextView
        android:id="@+id/show_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="0" />
</LinearLayout>

Mainactivity类:


public class MAinActivity extends Activity implements View.OnClickListener {
    private Button Start, Stop, Bind, UnBind, showbtn;
    private TextView showtext;
    private MyService.MyBinder myBinder;
    private MyService mService;
    boolean mBound = false;

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.servict_layout);
        Start = (Button) findViewById(R.id.service_start);
        Stop = (Button) findViewById(R.id.service_stop);
        Bind = (Button) findViewById(R.id.service_bind);
        UnBind = (Button) findViewById(R.id.service_unbind);
        showbtn = (Button) findViewById(R.id.show_oclick_btn);
        showtext = (TextView) findViewById(R.id.show_text);
        Start.setOnClickListener(this);
        Stop.setOnClickListener(this);
        Bind.setOnClickListener(this);
        UnBind.setOnClickListener(this);
        showbtn.setOnClickListener(this);
    }


    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.service_start://启动服务
                Intent startservice = new Intent(this, MyService.class);
                startService(startservice);
                Log.e("MAinActivity", "----------start button        getI=" + showI());
                showI();
                Toast.makeText(this, "start", Toast.LENGTH_SHORT).show();
                break;
            case R.id.service_stop://停止服务
                Intent stopservice = new Intent(this, MyService.class);
                stopService(stopservice);
                Log.e("MAinActivity", "----------stop button         getI=" + showI());
                showI();
                Toast.makeText(this, "stop", Toast.LENGTH_SHORT).show();
                break;
            case R.id.service_bind://绑定服务
                Intent bindservice = new Intent(this, MyService.class);
                bindService(bindservice, connection, BIND_AUTO_CREATE);
                Log.e("MAinActivity", "----------bind button         getI=" + showI());
                showI();
                Toast.makeText(this, "bind", Toast.LENGTH_SHORT).show();
                break;
            case R.id.service_unbind://解除绑定
                Log.e("MAinActivity", "----------Unbind button       getI=" + showI());
                if (mBound) {
                    unbindService(connection);
                    mBound = false;
                }
                showI();
                Toast.makeText(this, "unbind", Toast.LENGTH_SHORT).show();
                break;
            case R.id.show_oclick_btn://
                show();//获取后台I的值(没有绑定服务I显示为null)
                Log.e("MAinActivity", "----------show   button         getI=" + showI());
                break;
            case R.id.button:
                Intent intent = new Intent(this, OtherActivity.class);
                startActivity(intent);
                break;
        }
    }

    public String showI() {
        if (mService != null) {
            //showtext.setText(mService.getI() + "");
            return mService.getI() + "";
        } else {
            // showtext.setText("null");
            return "null";
        }
    }

    public void show() {
        if (mService != null) {
            showtext.setText(mService.getI() + "");

        } else {
            showtext.setText("null");

        }
    }

    //实例服务连接接口
    public ServiceConnection connection = new ServiceConnection() {
        //连接成功回调
        public void onServiceConnected(ComponentName name, IBinder service) {
            myBinder = (MyService.MyBinder) service;
            mService = myBinder.getService();
            mBound = true;
        }


        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
         /* if (mBound) {
            unbindService(connection);//这里注释了,当activity被销毁,绑定依然会解除,程序可能还会报错
            mBound = false;
        }*/
    }
}

贴完代码下面开始讲述我测试的过程:
运行程序之后的界面

依次点击 绑定、getI、启动、getI、解除、getI、停止 、getI按钮打印日志如下:
这里写图片描述
当我没启动service就让activity与service绑定(关联),service会执行onCreate()方法再执行onBind()方法,然后点击getI得到I为10,之后再启动服务service先后执行了onStartCommand()、onStart()方法点击getI得到I为3,当我点击解除关联,再getI依然可以得到I的值3,接着点击停止服务后,这时服务已经销毁service执行了onDestroy()方法,再次点击getI得到I值为4。这时就有问题了,为什么绑定解除了且service已经销毁了,activity任能获取service中方法执行结果?这里我的理解是绑定解除或service已经销毁activity是不能再获取service中的方法的,因为service是运行在主线程那么就是和activity在同一个UI线程里,在每一次执行后I的值会缓存在UI线程里。

本人初出茅庐,才疏学浅,正努力积累经验中。。。
如有不足和错误观点,欢迎指出纠正。

猜你喜欢

转载自blog.csdn.net/xxfen_/article/details/73467604