android四大组件之Service的学习(四大组件之路:三)&&进程的优先级

进程的优先级

每一个App被运行都会产生一个进程,而进程的存在是消耗资源的,如果不对进程进行操作随着进程越来越多,系统的资源总会被消耗干净。Android系统通过一定的策略,选择性杀死部分进程。这个策略就是对进程标记优先级,当需要杀死进程时,首先杀死优先级低的进程。

进程的优先级如下

  1. 前台进程(Foreground process)。它表明用户正在与该进程进行交互操作,android系统依据下面的条件来将一个进程标记为前台进程:

    • 该进程持有一个用户正在与其交互的Activity(也就是这个activity的生命周期方法走到了onResume()方法)。
    • 该进程持有一个Service,并且这个Service与一个用户正在交互中的Activity进行绑定。
    • 该进程持有一个前台运行模式的Service(也就是这个Service调用了startForegroud()方法)。
    • 该进程持有一个正在执行生命周期方法(onCreate()、onStart()、onDestroy()等)的Service。
    • 该进程持有一个正在执行onReceive()方法的BroadcastReceiver。 

    一般情况下,不会有太多的前台进程。杀死前台进程是操作系统最后无可奈何的做法。当内存严重不足的时候,前台进程一样会被杀死。

  2. 可见进程(Visible process)。它表明虽然该进程没有持有任何前台组件,但是它还是能够影响到用户看得到的界面。android系统依据下面的条件将一个进程标记为可见进程:

    • 该进程持有一个非前台Activity,但这个Activity依然能被用户看到(也就是这个Activity调用了onPause()方法)。例如,当一个activity启动了一个对话框,这个activity就被对话框挡在后面。
    • 该进程持有一个与可见(或者前台)Activity绑定的Service。
  3. 服务进程(Service process)。除了符合前台进程和可见进程条件的Service,其它的Service都会被归类为服务进程。 

  4. 后台进程(Background process)。持有不可见Activity(调用了onStop()方法)的进程即为后台进程。通常情况下都会有很多后台进程,当内存不足的时候,在所有的后台进程里面,会按照LRU(最近使用)规则,优先回收最长时间没有使用过的进程。 

  5. 空进程(Empty process)。不持有任何活动组件的进程。保持这种进程只有一个目的,就是为了缓存,以便下一次启动该进程中的组件时能够更快响应。当资源紧张的时候,系统会平衡进程缓存和底层的内核缓存情况进行回收。


相对应的,如果我们不想一个进程被杀死,那么可以采用一些手段来提升进程优先级。

由上面的总结可以知道,当一个进程持有一个Service,并且这个Service与用户正在交互的Activity进行绑定或者拥有一个正在执行生命周期方法的Service时进程的优先级是最高的,那么下面来介绍Service。

Service

1.Service的作用

我们为什么要引入Service?在众多的app中,有些app是需要长期在后台运行处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。例如一个音乐播放器,大多数时候是在后台运行播放音乐的。这个时候用到Service我们可以让他在后台执行某些任务,甚至当程序退出的时候我们也可以用Service来完成一些操作。

2.Service的特点

Service是无用户界面的

Service在后台运行

Service生命周期长

3.Service的类别


4.Service的两种启动方式

startService

通过startService启动后,service会一直无限期运行下去,只有外部调用了stopService()或stopSelf()方法时,该Service才会停止运行并销毁。

要创建一个这样的Service,你需要让该类继承Service类,然后重写以下方法:

  • onCreate()
    1.如果service没被创建过,调用startService()后会执行onCreate()回调;
    2.如果service已处于运行中,调用startService()不会执行onCreate()方法。
    也就是说,onCreate()只会在第一次创建service时候调用,多次执行startService()不会重复调用onCreate(),此方法适合完成一些初始化工作。

  • onStartCommand()
    如果多次执行了Context的startService()方法,那么Service的onStartCommand()方法也会相应的多次调用。onStartCommand()方法很重要,我们在该方法中根据传入的Intent参数进行实际的操作,比如会在此处创建一个线程用于下载数据或播放音乐等。

  • onBind()
    Service中的onBind()方法是抽象方法,Service类本身就是抽象类,所以onBind()方法是必须重写的,即使我们用不到。

  • onDestory()
    在销毁的时候会执行Service该方法。

这几个方法都是回调方法,且在主线程中执行,由android操作系统在合适的时机调用。

示例代码:

创建一个类继承自Service

public class MyService extends Service {


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

    @Override
    public void onCreate() {
        System.out.println("onCreat方法被执行了");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        System.out.println("onStartCommand方法被执行了");
        return super.onStartCommand(intent, flags, startId);
        
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("onDestroy方法被执行了");
    }
}

在xml中设置两个按钮

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="启动服务"
        android:onClick="Onclick1"
     />
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="停止服务"
        android:onClick="Onclick2"
         />

在AndroidManifest.xml中注册


   <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".MyBroadcastReceiver"
            >
            <intent-filter
                >
                <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>


            </intent-filter>
        </receiver>
        <service android:name=".MyService">

        </service>
    </application>


MainActivity


public class MainActivity extends AppCompatActivity {

    private Button button1;
    private Button button2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button1 = findViewById(R.id.button1);
        button2 = findViewById(R.id.button2);
        


    }
    public void  Onclick1(View v)
    {
        Intent intent = new Intent(this,MyService.class);
        startService(intent);
      
    }
    public void Onclick2(View v)
    {
        Intent intent = new Intent(this,MyService.class);
        stopService(intent);
    }


}

运行结果

点击按钮停止后



bindService

为什么要引入bindService开启服务的方法

如果想调用服务里的方法 直接创建类调用是不行的

因为Service中缺少上下文对象 我们可以通过bindService解决这个问题

由该方法启动的服务可以进行通信

bindService启动服务特点:

1.第一次点击按钮 执行服务的onCreat和onBind方法

2.当onBind方法返回为null时onServiceConnected方法是不执行的

3.调用者(Activity)销毁时Service也会被销毁


示例代码:

在新建子类继承Service类,并新建一个内部类继承自Binder类。

在Service中暴露出需要被调用的方法

public class MyService extends Service {
    public class MyBinder extends Binder{
        public void BinderMethod()
        {
            ServiceMethod();
        }


    }


    private MyBinder myBinder = new MyBinder();
    @Nullable
    @Override
    public IBinder onBind(Intent intent)
    {
        System.out.println("onBind方法被执行了");
        return myBinder;

    }

    @Override
    public void onCreate() {
        System.out.println("onCreat方法被执行了");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        System.out.println("onStartCommand方法被执行了");
        return super.onStartCommand(intent, flags, startId);

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("onDestroy方法被执行了");
    }

    @Override
    public boolean onUnbind(Intent intent) {
        System.out.println("onUnbind方法被执行了");
        return super.onUnbind(intent);

    }

    public int ServiceMethod()
    {

        Toast.makeText(this,"这是Service中的ServiceMethod方法",Toast.LENGTH_LONG).show();
        return 0;


    }
}

在AndroidManifest.xml配置Service

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <receiver android:name=".MyBroadcastReceiver"
            >
            <intent-filter
                >
                <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>


            </intent-filter>
        </receiver>
        <service android:name=".MyService">

        </service>
    </application>

为MainActivity设置三个按钮 分别为BindService UNBindService和调用Service中的方法

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="bindService"
        android:onClick="Onclick1"
     />
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="UnbindService"
        android:onClick="Onclick2"
         />
    <Button

        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="调用Service中的方法"
        android:onClick="Onclick3"
        />

在MainActvity中用实现各个按钮的点击事件

public class MainActivity extends AppCompatActivity {
    private Myconn myconn;
    private MyService.MyBinder myBinder;


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


    }
    public void  Onclick1(View v)
    {
        Intent intent = new Intent(this,MyService.class);
        myconn = new Myconn();

        bindService(intent,myconn,BIND_AUTO_CREATE);

    }
    public void Onclick2(View v)
    {
        unbindService(myconn);
    }
    public void Onclick3(View v)
    {
        myBinder.BinderMethod();
    }

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

    private class Myconn implements ServiceConnection
    {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
             myBinder= (MyService.MyBinder) service;


        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }

测试结果





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值