第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定

掌握Android Service:從基礎(chǔ)到高級(jí),涵蓋Started與Bound服務(wù)全解析

標(biāo)簽:
Android

什么是Service?
Service是Android四大组件之一,主要负责在后台执行长时间运行的任务,而无需用户界面。它就像是应用程序背后的默默工作者。

一、Service的主要功能

  1. 处理耗时任务: 比如网络数据下载、大文件处理或复杂的计算过程(这样可以避免因主线程执行这些任务而导致应用无响应)。
  2. 媒体播放: 对于音乐播放器或广播类的应用来说至关重要,即使用户关闭了当前界面,音乐也能继续播放。
  3. 文件的上传与下载: 即便应用被切换到后台,文件的上传和下载操作仍可继续进行。
  4. 跨进程通信: 利用AIDL技术实现不同应用之间的功能调用,例如一个天气服务可以向多个应用提供实时天气信息。
  5. 定时任务执行: 结合使用AlarmManager或WorkManager,在设定的时间点自动触发某些操作。
  6. 持续位置更新: 需要特别注意权限管理和电池消耗问题,能够不间断地获取用户的地理位置信息。

二、Service的两种启动方式及使用方法

Service的行为模式及其生命周期管理取决于其启动方式:

  1. 启动式Service (Started Service)

    示例场景 - 启动一个文件下载服务:

    
    Intent downloadIntent = new Intent(this, DownloadService.class);
    downloadIntent.putExtra("url", "https://example.com/bigfile.zip");
    startService(downloadIntent); 
    
    public class DownloadService extends Service {
       @Override
       public void onCreate() {
           super.onCreate();
    
       }
    
       @Override
       public int onStartCommand(Intent intent, int flags, int startId) {
    
           String url = intent.getStringExtra("url");
    
           new DownloadTask().execute(url);
    
           return START_NOT_STICKY; 
       }
    
       private class DownloadTask extends AsyncTask<String, Void, Void> {
           @Override
           protected Void doInBackground(String... urls) {
    
               stopSelf(); 
               return null;
           }
       }
    
       @Override
       public void onDestroy() {
           super.onDestroy();
    
       }
    
       @Nullable
       @Override
       public IBinder onBind(Intent intent) {
           return null; 
       }
    }
    

    绑定服务 (Bound Service)

  • 作用: 绑定服务主要用于提供客户端-服务器接口,让其他组件(例如 Activity)可以绑定到服务上进行交互。这种交互包括调用方法、获取数据或监听状态。比如,音乐播放器服务可以提供 play()pause()getPosition() 等方法供 Activity 调用;股票应用程序的服务则可以提供实时股价数据流。

  • 如何绑定: 在 Activity 或其他组件中,通过调用 bindService(Intent, ServiceConnection, int) 方法来绑定服务。

  • 特点:

    • 多个组件可以同时绑定到同一个服务。
    • 组件与服务之间建立了一条通信通道(通常是 Binder 对象),使得组件可以直接调用服务提供的方法。
    • 当所有绑定者都解绑(调用 unbindService())后,系统通常会销毁该服务(除非它同时也被 startService() 启动了)。
    • 如果绑定服务的组件(如 Activity)被销毁,系统会自动解绑该服务。
  • 生命周期方法调用顺序:

    • 服务启动时,首先调用 onCreate(),然后是 onBind(Intent)。此时服务开始运行,客户端可以通过返回的 IBinder 对象与服务通信。
    • 当最后一个客户端解绑时,调用 onUnbind(Intent),最后调用 onDestroy() 销毁服务。
    • onBind() 是关键步骤,它返回一个 IBinder 对象,作为客户端与服务之间的桥梁。

实现绑定服务的三种方式:

  1. 扩展 Binder 类(最简单,适用于同一进程内):

    • 在服务内部创建一个继承自 Binder 的类,并提供公共方法供客户端调用。
    • onBind() 方法中返回这个 Binder 实例。
    • 客户端在 ServiceConnectiononServiceConnected() 回调中获取并转换这个 Binder 实例,从而调用服务中的方法。
    
    public class LocalService extends Service {
      private final IBinder binder = new LocalBinder(); 
    
      public class LocalBinder extends Binder {
          LocalService getService() {
              return LocalService.this; 
          }
      }
    
      @Override
      public IBinder onBind(Intent intent) {
          return binder;
      }
    
      public int getRandomNumber() {
          return new Random().nextInt(100);
      }
    }
    
    public class MainActivity extends Activity {
      LocalService mService;
      boolean mBound = false;
    
      private ServiceConnection connection = new ServiceConnection() {
          @Override
          public void onServiceConnected(ComponentName name, IBinder service) {
    
              LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
              mService = binder.getService(); 
              mBound = true;
    
          }
    
          @Override
          public void onServiceDisconnected(ComponentName name) {
              mBound = false;
          }
      };
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
    
          Intent intent = new Intent(this, LocalService.class);
          bindService(intent, connection, Context.BIND_AUTO_CREATE); 
      }
    
      @Override
      protected void onStop() {
          super.onStop();
          if (mBound) {
              unbindService(connection); 
              mBound = false;
          }
      }
    }
    
    • 2. 使用 Messenger(跨进程较简单):

    • 服务端定义一个 Handler,用来处理客户端通过 Message 对象发送的请求。
    • onBind() 方法中返回一个基于 Handler 创建的 Messenger
    • 客户端获取到 Messenger 后,可以向服务端发送 Message 对象。服务端也可以回复消息。
    • 相比 AIDL,这种方式更简单,但通信方式较为单一,只能是单向或请求-响应式的,灵活性不如 AIDL。
  • 服务端实现

public class MessengerService extends Service {
    private static final String TAG = "MessengerService";
    public static final int MSG_SAY_HELLO = 1;
    public static final int MSG_REPLY = 2;

    private static class ServiceHandler extends Handler {
        private final WeakReference<Context> mContextRef;
        private Messenger mClientMessenger; 

        ServiceHandler(Context context) {
            mContextRef = new WeakReference<>(context);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    Log.d(TAG, "收到客户端消息: " + msg.getData().getString("data"));

                    mClientMessenger = msg.replyTo;
                    if (mClientMessenger != null) {
                        try {

                            Message replyMsg = Message.obtain(null, MSG_REPLY);
                            Bundle bundle = new Bundle();
                            bundle.putString("reply", "你好客户端,我是服务端");
                            replyMsg.setData(bundle);
                            mClientMessenger.send(replyMsg);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    private final Messenger mMessenger = new Messenger(new ServiceHandler(this));

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind");
        return mMessenger.getBinder(); 
    }
}

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    private Messenger mServiceMessenger; 
    private boolean mBound; 

    private static class ClientHandler extends Handler {
        private final WeakReference<MainActivity> mActivityRef;

        ClientHandler(MainActivity activity) {
            mActivityRef = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = mActivityRef.get();
            if (activity != null && msg.what == MessengerService.MSG_REPLY) {
                String reply = msg.getData().getString("reply");
                Log.d(TAG, "收到服务端回复: " + reply);
                Toast.makeText(activity, reply, Toast.LENGTH_SHORT).show();
            }
        }
    }

    private final Messenger mClientMessenger = new Messenger(new ClientHandler(this));

    private final ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "服务已连接");

            mServiceMessenger = new Messenger(service);
            mBound = true;

            sendMessageToService();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "服务已断开");
            mServiceMessenger = null;
            mBound = false;
        }
    };

    private void sendMessageToService() {
        if (!mBound) return;
        try {

            Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO);
            Bundle data = new Bundle();
            data.putString("data", "你好服务端,我是客户端");
            msg.setData(data);

            msg.replyTo = mClientMessenger;

            mServiceMessenger.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_bind).setOnClickListener(v -> bindService());
        findViewById(R.id.btn_unbind).setOnClickListener(v -> unbindService());
    }

    private void bindService() {
        Intent intent = new Intent(this, MessengerService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    private void unbindService() {
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService();
    }
}
  • 3. 使用 AIDL(Android接口定义语言 - 用于跨进程复杂交互):
    AIDL是一种帮助不同应用进程之间进行通信的工具。当你需要在Service和其他应用程序组件间传递复杂数据时,AIDL就派上用场了。通过定义一个AIDL接口文件,你可以指定哪些方法可以被远程调用,以及这些方法的参数和返回值类型。这样,无论服务运行在哪个进程中,其他应用都能轻松地与它进行交互。

    -   定义 AIDL 接口文件 (.aidl),描述服务公开的方法。
    -   编译时 Android SDK 工具会生成对应的 Java 接口和 Stub 类。
    -   服务继承 `Stub` 类并实现 AIDL 接口定义的方法,在 `onBind()` 中返回这个 `Stub` 实例。
    -   客户端绑定后,将 `onServiceConnected()` 返回的 `IBinder` 转换成 AIDL 接口类型,即可调用远程方法。
    -   这是实现**跨进程通信 (IPC)**  最强大但也最复杂的方式。系统服务(如 `LocationManagerService`)大多通过 AIDL 暴露接口。
    

三、关键概念与注意事项

  1. 生命周期: 理解StartedBound两种模式下的生命周期回调(如onCreate, onStartCommand, onBind, onUnbind, onDestroy)及其触发条件至关重要。记住,服务不会自动停止!启动服务需要手动停止,而绑定服务则需要所有客户端解绑后才能停止。

  2. 主线程警告: 所有Service的生命周期方法默认都在主线程(UI线程)上执行。切记不要在onStartCommand()onBind()中直接执行耗时操作,否则会导致应用无响应(ANR)。正确的做法是使用工作线程(例如Thread, HandlerThread, ExecutorService, 或者推荐使用的Kotlin协程/RxJava)或IntentService(详见下文)来处理耗时任务。

  3. 前台服务 (Foreground Service):

    • 为什么需要? 自Android 8.0 (Oreo)起,普通后台服务受到严格限制,容易被系统终止。对于需要长时间运行且用户可感知的服务(如音乐播放、导航、文件下载),应将其提升为前台服务。
    • 怎么做? 在服务中调用startForeground(int id, Notification notification),并提供一个持续显示的通知告知用户服务正在运行。这将提高服务的优先级,减少被系统杀死的风险。
    • 完成任务后,可以通过调用stopForeground(boolean removeNotification)将服务降回后台状态(注意,这并不会停止服务本身)。
  4. IntentService:

    • 这是一个专门用于处理异步一次性启动请求的Service子类。
    • 优点: 内置了工作线程,请求会按顺序排队处理(onHandleIntent(Intent)会在工作线程上执行),并且当所有请求处理完毕后会自动调用stopSelf()停止服务。
    • 缺点: 不支持绑定,不能直接处理并发任务(只能串行执行),并且自Android 8.0起也受到后台限制的影响。适用于简单的任务。需要注意的是,从Android 11开始,IntentService已被标记为废弃,建议改用JobIntentService(同样已废弃)或更现代的WorkManager
  5. Android 8.0+ 后台限制:

  6. 服务保活误区:
    • 避免通过startForeground()隐藏通知来保持服务运行,因为这样会被系统检测到并终止。
    • 不要频繁使用startService()AlarmManager唤醒服务,这不仅浪费电量还会影响用户体验,新版本的Android对此有严格的限制。
    • 正确的方法: 接受服务可能会被系统终止的事实。使用前台服务让用户知道服务正在运行;利用WorkManager确保任务最终会被执行;在服务重启时(通过onStartCommand中的flags参数)考虑恢复之前的状态;及时保存重要数据(如存入数据库或文件)以防丢失。

四、总结

點(diǎn)擊查看更多內(nèi)容
TA 點(diǎn)贊

若覺得本文不錯(cuò),就分享一下吧!

評(píng)論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評(píng)論
  • 收藏
  • 共同學(xué)習(xí),寫下你的評(píng)論
感謝您的支持,我會(huì)繼續(xù)努力的~
掃碼打賞,你說多少就多少
贊賞金額會(huì)直接到老師賬戶
支付方式
打開微信掃一掃,即可進(jìn)行掃碼打賞哦
今天注冊(cè)有機(jī)會(huì)得

100積分直接送

付費(fèi)專欄免費(fèi)學(xué)

大額優(yōu)惠券免費(fèi)領(lǐng)

立即參與 放棄機(jī)會(huì)
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)

舉報(bào)

0/150
提交
取消