读书笔记-Android服务

读书笔记-Android服务


什么是服务?
  • 服务是Android中实现程序后台运行的解决方案,比较适合去用来执行不需要交互,而默默在后台运行的程序,相比于linux的系统中比较像守护进程。
  • 但是他不是真正的独立进程,而是依赖于产生服务的应用进程,这样我们就可以很清楚的知道他们之间的生命周期关系。

1.服务的两种启动方式之间的区别

服务有两种启动的方式:

(1).start方式:

  • 特点:
  • 使用步骤:

1.定义一个类继承Service

2.在Manifest.xml文件中配置该Service
3.使用Context的startService(Intent)方法启动该Service
4.不再使用时,调用stopService(Intent)方法停止该服务

  • 生命周期:

onCreate()—>onStartCommand()(onStart()方法已过时)  —> onDestory()

  • 说明:

如果服务已经开启,不会重复的执行onCreate(), 而是会调用onStart()和onStartCommand()。服务停止的时候调用onDestory()。服务只会被停止一次(一个实例)。

(2).bind方式:

  • 特点:

bind的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。

绑定者可以调用服务里面的方法。

  • 使用步骤:

1.定义一个类继承Service

2.在Manifest.xml文件中配置该Service

3.使用Context的bindService(Intent, ServiceConnection, int)方法启动该Service

4.不再使用时,调用unbindService(ServiceConnection)方法停止该服务

  • 生命周期:

onCreate() —>onBind()—>onunbind()—>onDestory()onCreate() —>onBind()—>onunbind()—>onDestory()

2.比较Service与IntentService的异同:

(1).Service

Service 是长期运行在后台的应用程序组件。

Service 不是一个单独的进程,它和应用程序在同一个进程中,Service 也不是一个线程,它和线程没有任何关系,所以它不能直接处理耗时操作。如果直接把耗时操作放在 Service 的 onStartCommand() 中,很容易引起 ANR .如果有耗时操作就必须开启一个单独的线程来处理

**
(2).IntentService

IntentService 是继承于 Service 并处理异步请求的一个类,在 IntentService 内有一个工作线程来处理耗时操作,启动 IntentService 的方式和启动传统 Service 一样,同时,当任务执行完后,IntentService 会自动停止,而不需要我们去手动控制。另外,可以启动 IntentService 多次,而每一个耗时操作会以工作队列的方式在IntentService 的 onHandleIntent 回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

而且,所有请求都在一个单线程中,不会阻塞应用程序的主线程(UI Thread),同一时间只处理一个请求。 那么,用 IntentService 有什么好处呢?首先,我们省去了在 Service 中手动开线程的麻烦,第二,当操作完成时,我们不用手动停止 Service

总结来说就是,IntentService帮助我们开线程的麻烦,以及帮助我们停止线程。

3.Activity与Service之间如何进行通信,请编程进行说明:

我将通过编程实例来进行演示如何活动和服务之间进行通信:

我这个项目是比较全的,囊括了start,bind,以及IntentService,不过还是重点说明如何实现通讯的吧:

(1).再服务类MuService中创建一个DownloadBinder类,继承于Binder,然后在里面写两个方法(用来模拟进程对后台的访问),然后再创建一个DownloadBInder的实例,再onBind()这个方法这种返回这个实例:

package com.ncu.servicetest;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import androidx.core.app.NotificationCompat;

public class MyService extends Service {

    public MyService() {
    }

    private DownloadBinder mBinder = new DownloadBinder();

    class DownloadBinder extends Binder {

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

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

    }

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

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("MyService", "onCreate executed");
        Intent intent = new Intent(this, MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
        Notification notification = new NotificationCompat.Builder(this)
                .setContentTitle("This is content title")
                .setContentText("This is content text")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                .setContentIntent(pi)
                .build();
        startForeground(1, notification);
    }

    @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");
    }

}

(2).在布局文件activity_main.xml中放两个链接模拟活动于服务链接的按钮以及断开连接的按钮:

<?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" />

    <Button
        android:id="@+id/bind_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Bind Service" />

    <Button
        android:id="@+id/unbind_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Unbind Service" />

    <Button
        android:id="@+id/start_intent_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start IntentService" />

</LinearLayout>

(3).编写MainActivity.java文件:
这里面写一个ServiceConnection的匿名类,在里面重写OnSeviceConnected()方法以及OnServiceDisconnected()方法,这两个方法我们可以得到DownloadBinder实例。
这样可以使用DownloadBinder来调用我们服务中的方法了。
最后需要使用biindService()方法来进行绑定。
unbindService()来接触绑定。

package com.ncu.servicetest;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private MyService.DownloadBinder downloadBinder;

    private ServiceConnection connection = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            downloadBinder = (MyService.DownloadBinder) service;
            downloadBinder.startDownload();
            downloadBinder.getProgress();
        }
    };

    @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);
        Button startIntentService = (Button) findViewById(R.id.start_intent_service);
        startIntentService.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;
            case R.id.start_intent_service:
                // 打印主线程的id
                Log.d("MainActivity", "Thread id is " + Thread.currentThread(). getId());
                Intent intentService = new Intent(this, MyIntentService.class);
                startService(intentService);
                break;
            default:
                break;
        }
    }

}

最后我们来看下我们模拟绑定以及接触绑定的效果:
image.png
我们看下点击绑定以及接触绑定会触发函数事件:
第一行是我们创建连接绑定,第二行和第三行就是活动访问服务的触发结果,最后一行表示解除绑定。
image.png

4.远程服务(或称跨进程服务)有何实际作用?请以Android Studio开发环境为例,说明远程服务的使用过程

远程服务与本地服务最大的区别是:远程Service与调用者不在同一个进程里(即远程Service是运行在另外一个进程);而本地服务则是与调用者运行在同一个进程里。

简单的来说就是本服务可以被非本进程调用,这样可以方便其他的应用或者进程来使用自己的服务,或者自己进程使用其他的服务,实现一个服务多个进程可以共享,节约了资源和空间。

下面以案例来说明远程的服务使用过程:

1.创建一个aidl:
并且里面加入一个函数(外部访问的):
image.png
2.创建服务,然后在里面的实现这个函数:
image.png
3.然后不断的输出data。
这样就完成了服务器端。
然后我们开始客户端:
获得到IAppServiceRemoteBinder的binder来调用函数setData,并且传值进去,这样就会修改服务器中的值了。
 image.png

对了两个的都要有android提供的远程dial的文件,而且路径要保持一致:
image.png
这样就可以实现一个程序去调用另外一个程序的服务,通过dial。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值