Service基本使用

2019-08-09  本文已影响0人  者文_

Service是android中实现程序后台运行的解决方案,适合去执行那些不需要和用户交互且长期运行的任务。服务的运行不依赖任何用户界面。

Service并不是运行在一个独立的进程当中,依赖于创建服务时所在的应用程序进程。某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止

1. Service使用

image

Android中使用Service的方式有两种

1.1 关键方法

1.2 startService()启动

使用Service的一般流程:自定义service,重写相关方法,调用即可

简单示例:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/start_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="start service" />
    <Button
       android:id="@+id/stop_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Stop Service"/>

</LinearLayout>

自定义Service

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("MyService", "onCreate executed");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("MyService", "onStartCommand executed");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("MyService", "onDestroy executed");
    }
}

调用服务

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button startService = (Button) findViewById(R.id.start_service);
        Button stopService = (Button) findViewById(R.id.stop_service);
        startService.setOnClickListener(this);
        stopService.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.start_service:
                Intent startIntent = new Intent(this, MyService.class);
                startService(startIntent);
                break;
            case R.id.stop_service:
                Intent stopIntent = new Intent(this, MyService.class);
                stopService(stopIntent);
                break;
            default:
                break;

        }
    }
}

注册服务(四大组件都要注册)

<service
    android:name=".MyService"
    android:enabled="true"
    android:exported="true"></service>

备注

1.3 bindService()启动

前述的方式启动服务之后,活动与服务基本就没有关系了。而用Binder方法可以让活动和服务的关系更加紧密,实现二者的通信。

1.3.1 知识介绍

1.3.2 步骤与实例

一般步骤如下

实例

public class MyService extends Service {

    private DownloadBinder mBinder = new DownloadBinder();

    class DownloadBinder extends Binder {

        public void startDownload() {
            Log.d("MyService", "startDownload");
        }

        public int getProgress() {
            Log.d("MyService", "getProgress executed");
            return 0;
        }
    }

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return mBinder;
    }
    ...
 }
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    //绑定该Service的类中定义一个ServiceConnection对象
    private MyService.DownloadBinder downloadBinder;
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            downloadBinder = (MyService.DownloadBinder) service;
            downloadBinder.startDownload();
            downloadBinder.getProgress();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button startService = (Button) findViewById(R.id.start_service);
        Button stopService = (Button) findViewById(R.id.stop_service);
        startService.setOnClickListener(this);
        stopService.setOnClickListener(this);
        Button bindService = (Button) findViewById(R.id.bind_service);
        Button unbindService = (Button) findViewById(R.id.unbind_service);
        bindService.setOnClickListener(this);
        unbindService.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.start_service:
                Intent startIntent = new Intent(this, MyService.class);
                startService(startIntent);
                break;
            case R.id.stop_service:
                Intent stopIntent = new Intent(this, MyService.class);
                stopService(stopIntent);
                break;
            case R.id.bind_service:
                Intent bindIntent = new Intent(this, MyService.class);
                bindService(bindIntent, connection, BIND_AUTO_CREATE);
                break;
            case R.id.unbind_service:
                unbindService(connection);
                break;
            default:
                break;

        }
    }
}

备注

2. IntentService使用

如果直接把耗时线程放到Service中的onStart()方法中,容易引起ANR(Application Not Responding)异常.Service不是一个单独的进程,与应用程序同在一个进程中;Service不是一个线程,避免在Service中进行耗时操作

我们可以用多线程技术,在服务的每个具体方法里开启一个子线程,在这里去处理耗时的逻辑,则一个标准的逻辑可以写成:

public class MyService extends Service {
    ...
    @override
        public int onStartCommand(Intent intent, int flags, int startId) {
        new Thread(new Runnable() {
            @override
            public void run() {
                //处理具体逻辑
                stopself();//执行完毕自动停止服务
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }
}

前述方法容易忘记开启线程,或者忘记调用stopSelf()方法。

IntentService继承于Service并处理异步请求的一个类,在IntentService中有一个工作线程来处理耗时操作,请求的Intent记录会加入队列。

2.1 工作流程

客户端通过startService(Intent)来启动IntentService,当任务执行完后,IntentService会自动停止;可以启动IntentService多次,每个耗时操作会以工作队列的方式在IntentService的 onHandleIntent回调方法中执行,并且每次只会执行一个工作线程,执行完一,再到二这样!

实例:

public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d("MyIntentService", "Thread id is" + Thread.currentThread().getId());
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("MyIntentService", "onDestory ececuted");
    }
}

备注

3. 前台服务(待补充)

Service一般都是运行在后台的,但是Service的系统优先级 还是比较低的,当系统内存不足的时候,就有可能回收正在后台运行的Service, 对于这种情况我们可以使用前台服务,从而让Service稍微没那么容易被系统杀死。

前台服务与普通服务之间最大的区别在于:它会有一个正在运行的图标在系统的状态栏显示,下拉状态栏可以看到更加详细的信息。

上一篇 下一篇

猜你喜欢

热点阅读