展開說說:Android四大組件之Service使用

Service一定要開啟子線程才可以執行耗時任務嗎?不完全是吧。

Service是Android系統中的四大組件之一,它是一種沒有可視化界面,運行于后臺的一種服務程序屬于計算型組件,用來在后臺執行持續性的計算任務,重要性僅次于Activity活動。

本文分四塊來記錄,分別是普通Service、IntentService、ForegroundService,其中普通service根據運行狀態不同分為startService啟動的Service和bindService綁定的Service。

先定義一個Service子實現類,普通Service的啟動的Service和bindService綁定的Service共用這一個Service類。

public class ServiceJia extends Service {private static final String TAG = ServiceJia.class.getName();@Nullable@Overridepublic IBinder onBind(Intent intent) {Log.e(TAG, "onBind: " );return new JiaBinder();}@Overridepublic void onCreate() {super.onCreate();Log.e(TAG, "onCreate: " );}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.e(TAG, "onStartCommand: " );new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(30000);Log.e(TAG, "onStartCommand:    等了半分鐘" );} catch (InterruptedException e) {e.printStackTrace();}}}).start();Log.e(TAG, "onStartCommand:    -end" );return super.onStartCommand(intent, flags, startId);}//用于bindService時和activity交互public static class JiaBinder extends Binder {public void doSomething(String something){Log.e(TAG, "JiaBinder  --doSomething: "+something );}public void onClick(String something){Log.e(TAG, "JiaBinder  --onClick: "+something );}}}

1、startService啟動Service和停止

通過startService()創建啟動的service可以一直運行下去,必須自己調用stopSelf()方法或者其他組件調用stopService()方法來停止。適用于不和其他組件通訊的業務。

?//不可以阻塞線程做耗時操作,比如這樣:

try {
?????Thread.sleep(30000);
?????} catch (InterruptedException e) {
???????????e.printStackTrace();
??????}
?程序閃退報錯:
2023-12-02 09:46:39.584 1592-1795/? E/ActivityManager: ANR in com.example.testdemo3?PID: 29467
Reason: executing service com.example.testdemo3/.service.ServiceJia
Load: 46.58 / 46.1 / 46.01
CPU usage from 70164ms to 0ms ago (2023-12-02 09:45:28.698 to 2023-12-02 09:46:38.862) with 99% awake:

啟動和關閉服務:

startService.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {String text = startService.getText().toString();if ("startService".equals(text)){startService.setText("stopService");serviceIntent = new Intent(ServiceActivity.this, ServiceJia.class);startService(serviceIntent);}else if ("stopService".equals(text)){if (stopService(serviceIntent)){ //真停了再修改按鈕的文字顯示startService.setText("startService");}}}
});

2、bindService綁定Service和解綁

調用bindService()來創建,調用方可以通過一個IBinder接口和service進行通信,需要通過ServiceConnection建立連接多用于有交互的場景。

只能調用方通過unbindService()方法來斷開連接。調用方可以和Service通訊,并且一個service可以同時和多個調用方存在綁定關系解除綁定也需要所有調用全部解除綁定之后系統會銷毀service

綁定和解綁服務:

String text = bindService.getText().toString();
if ("bindService".equals(text)){
if (serviceIntent == null)serviceIntent = new Intent(ServiceActivity.this, ServiceJia.class);if (bindService(serviceIntent,serviceConnection, Context.BIND_AUTO_CREATE)){bindService.setText("unBindService");}
}else if ("unBindService".equals(text)){unbindService(serviceConnection);bindService.setText("bindService");
}

//連接成功,可以通過Binder調用綁定的service中的方法,比如jiaBinder.doSomething("start conncetion");

serviceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {Log.e(TAG, "onServiceConnected: " );jiaBinder = (ServiceJia.JiaBinder) iBinder;//連接成功,調用綁定的service中的方法jiaBinder.doSomething("start conncetion");}@Overridepublic void onServiceDisconnected(ComponentName componentName) {Log.e(TAG, "onServiceDisconnected: " );}@Overridepublic void onBindingDied(ComponentName name) {Log.e(TAG, "onBindingDied: " );}@Overridepublic void onNullBinding(ComponentName name) {Log.e(TAG, "onNullBinding: " );}
};

3、IntentService

它可以解決第一句中“Service一定要開啟子線程才可以執行耗時任務嗎?”的問題。

IntentService 是 Android 中的一個服務,繼承自 Service 類,并在單獨的工作線程中執行任務,避免了多線程處理異步任務我們可以在onHandleIntent生命周期方法中執行耗時任務,不用開啟子線程:

注意這里是繼承IntentService

還有就是繼承IntentService必須聲明一個空參構造方法否則會報錯刪除?

public class MyIntentService extends IntentService {public static final String TAG = "MyIntentService";/*** Creates an IntentService.  Invoked by your subclass's constructor.* @param name Used to name the worker thread, important only for debugging.* 如果name字段為空,字符串就是worker thread的名字*/public MyIntentService(String name) {super(name);}public MyIntentService() {super(TAG);}/*** 可以做耗時任務* @param intent*/@Overrideprotected void onHandleIntent(@Nullable Intent intent) {String type = intent.getStringExtra("type");try {Log.e(TAG, "onHandleIntent:  -start" );Thread.sleep(10000);Log.e(TAG, "onHandleIntent:  -end" );} catch (InterruptedException e) {e.printStackTrace();}}

啟動和關閉IntentService

intentService.setOnClickListener(new View.OnClickListener() {@RequiresApi(api = Build.VERSION_CODES.O)@Overridepublic void onClick(View v) {String text = intentService.getText().toString();if ("startIntentService".equals(text)){intentService.setText("stopIntentService");intentServiceIntent = new Intent(ServiceActivity.this, MyIntentService.class);startService(intentServiceIntent);}else if ("stopIntentService".equals(text)){boolean b = stopService(intentServiceIntent);Log.e(TAG, "onClick: stopIntentService= "+b );if (b){ //真停了再修改按鈕的文字顯示intentService.setText("startIntentService");}}}
});

這里有一個比較坑的地方就是,必須指定一個空參構造函數,否則運行就會報錯。

4、前臺服務

前臺服務用于執行用戶可察覺的操作。前臺服務會顯示狀態欄通知,讓用戶知道當前應用正在前臺執行任務并消耗系統資源。用戶可以通過點擊通知來與應用進行交互。

值得注意的兩個點:

  • 除了在AndroidManifest.xml注冊服務之外,還需要申請前臺服務的權限,否則會閃退。

<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

  • Build.VERSION_CODES.O及以上的系統,需要單獨NotificationManager需要設置NotificationChannel否則會閃退,具體見下面代碼。

閃退報錯信息:“android.app.RemoteServiceException: Bad notification for startForeground

使用上和普通Service類似同樣繼承Service,但是要設置前臺服務通知

startForeground(1000,notification);定義前臺服務:
public class MyForegroundService extends Service {@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Notification.Builder builder = null;if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {builder = new Notification.Builder(this,getChannelId("com.example.testdemo.service","MyForegroundService"));Notification notification = builder.setContentTitle("我是前臺服務").setContentText("目前運行平穩").setSmallIcon(R.mipmap.ic_launcher).build();//設置前臺服務startForeground(1000,notification);}else {//設置前臺服務startForeground(1000,new Notification());}//被殺以后還會再次創建return START_STICKY;}@RequiresApi(api = Build.VERSION_CODES.O)private String getChannelId(String channelId, String channelName) {NotificationChannel notificationChannel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE);notificationChannel.setLightColor(Color.BLUE);notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);notificationManager.createNotificationChannel(notificationChannel);return channelId;}
}

啟動和關閉前臺服務:

 foregroundService.setOnClickListener(new View.OnClickListener() {@RequiresApi(api = Build.VERSION_CODES.O)@Overridepublic void onClick(View v) {String text = foregroundService.getText().toString();if ("startForegroundService".equals(text)){foregroundService.setText("stopForegroundService");foregroundServiceIntent = new Intent(ServiceActivity.this, MyForegroundService.class);
//                    startService(intentServiceIntent);startForegroundService(foregroundServiceIntent);}else if ("stopForegroundService".equals(text)){boolean b = stopService(foregroundServiceIntent);Log.e(TAG, "onClick: stopIntentService= "+b );if (b){ //真停了再修改按鈕的文字顯示foregroundService.setText("startForegroundService");}}}});

本文主要是記錄了四種使用服務經常遇到的問題,后面再分析生命周期和源碼。

才疏學淺,如有錯誤,歡迎指正,多謝。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/39649.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/39649.shtml
英文地址,請注明出處:http://en.pswp.cn/web/39649.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

分子AI預測賽筆記

#AI夏令營 #Datawhale #夏令營 Taks1 跑通baseline 根據task1跑通baseline 注冊賬號 直接注冊或登錄百度賬號&#xff0c;etc fork 項目 零基礎入門 Ai 數據挖掘競賽-速通 Baseline - 飛槳AI Studio星河社區 啟動項目 選擇運行環境&#xff0c;并點擊確定&#xff0c;沒…

臺燈學生用哪個牌子最好?學生用臺燈品牌排行榜分析

臺燈學生用哪個牌子最好&#xff1f;護眼臺燈在近年來成為家長和長時間使用電子設備人群關注的家電/學生產品。對于家中有孩子或經常面對電子屏幕的人士來說&#xff0c;很多人可能已經對這類產品有所了解并進行了購買。然而&#xff0c;部分家長對護眼臺燈的認識還不夠深入&am…

不同類型uORF對mORF翻譯效率的影響

在您提供的文獻《不同類型的uORF在真核生物基因表達中的調控潛力》中&#xff0c;對于不同類型的起始密碼子的uORF及其對下游主開放閱讀框&#xff08;mORF&#xff09;翻譯效率的影響進行了詳細的討論。以下是這些影響的主要總結&#xff1a; uORF的起始密碼子類型&#xff1a…

FFT 簡單基礎(matlab

使用 fs 進行采樣&#xff0c;進行 N點FFT 選擇顯示0~N/21點的幅值 橫坐標對應頻率計算公式&#xff1a; fs * n / N 舉個梨子&#xff1a; 頻率2kHz采樣1s&#xff0c;得到2000個點的序列y(n) 對序列y(n)做4096點的FFT 幅值響應對應的橫坐標頻率…

機器人控制系列教程之Stewart平臺簡介和運動學分析

Stewart平臺簡介及應用場景 六自由度 Stewart 并聯機器人結構簡圖如下圖所示&#xff0c;主要有一個固定平臺和一個移動平臺以及六個可伸縮的推桿組成&#xff0c;通常情況下&#xff0c;固定平臺與底座連接&#xff0c;移動平臺在空間具有六個自由度&#xff0c;通過六個推桿…

數據結構——求兩個數的最大公因子

#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> 數據結構——求兩個數的最大公因子 要求&#xff1a;必須采用遞歸和非遞歸兩種方法 非遞歸&#xff1a; int main() { int a 0; int b 0; scanf("%d %d", &a, &b); int c a…

攻防演練,怎么掃描一個網站

在 Ubuntu 22.04 上&#xff0c;你可以使用多種掃描工具來進行網站掃描。以下是一些常見的掃描工具以及它們的安裝方法&#xff1a; Nmap: Nmap 是一個開源的網絡掃描工具&#xff0c;用于發現網絡和安全審計。安裝命令&#xff1a;sudo apt update sudo apt install nmapNikto…

價格很實惠,希喂、愛立方、生生不息主食凍干抗得住實測嗎?

在挑選主食凍干時&#xff0c;許多寵物主人都會感到頭疼。盡管主食凍干相較于普通貓糧具有諸多優勢&#xff0c;但其價格也相對高昂。這導致許多寵物主人擔心高價購買的主食凍干可能營養價值并不理想。然而&#xff0c;在選擇時&#xff0c;我們還需要考慮其他重要因素&#xf…

Spring MVC 中 使用 RESTFul 實現用戶管理系統

1. Spring MVC 中 使用 RESTFul 實現用戶管理系統 文章目錄 1. Spring MVC 中 使用 RESTFul 實現用戶管理系統2. 靜態頁面準備2.1 user.css2.2 user_index.html2.3 user_list.html2.4 user_add.html2.5 user_edit.html 3. SpringMVC環境搭建3.1 創建module&#xff1a;usermgt3…

tapd 與國內外主流的8大項目管理軟件大對比

對比Tapd與8大項目管理工具&#xff1a;PingCode、Worktile、Redmine、Teambition、廣聯達、Jira、禪道、飛書。 Tapd 是騰訊推出的一款敏捷開發管理工具&#xff0c;特別適合那些需要高效協作和快速迭代的敏捷開發團隊。它支持多種敏捷方法論&#xff0c;包括Scrum和Kanban&am…

《詳細指南:本地部署Ollama大型模型的完整步驟》

《詳細指南&#xff1a;本地部署Ollama大型模型的完整步驟》 引言 Ollama是一個高性能的AI模型部署平臺&#xff0c;支持在本地輕松部署大型語言模型。本指南將詳細介紹如何在本地環境中部署Ollama&#xff0c;并運行一個大型模型。 環境要求 操作系統&#xff1a;Windows/…

數學建模------Matlab數據可視化

目錄 1.plot函數 &#xff08;1&#xff09;函數介紹 &#xff08;2&#xff09;參數介紹 &#xff08;3&#xff09;圖形美化 &#xff08;4&#xff09;背景更改 &#xff08;5&#xff09;多組繪制 &#xff08;6&#xff09;圖形疊加 &#xff08;7&#xff09;添加…

Elasticsearch備份數據到本地,并導入到新的服務 es 服務中

文章目錄 使用elasticsearch-dump工具備份安裝node.js(二進制安裝)解壓設置環境變量安裝elasticsearch-dump docker安裝使用ES備份文件到本地 使用elasticsearch-dump工具備份 這個工具備份時間比較長 安裝node.js(二進制安裝) wget https://nodejs.org/dist/v16.18.0/node-…

C語言 求分數序列的和

求分數序列2/1&#xff0c;3/2&#xff0c;5/3&#xff0c;8/5&#xff0c;13/8&#xff0c;21/13…。求出數列的n項和&#xff0c;n由鍵盤輸入&#xff0c;并計算n20的結果 這個程序計算分數序列的前 n 項和&#xff0c;并輸出 n 20 時的結果。 #include <stdio.h>in…

華為機試HJ13句子逆序

華為機試HJ13句子逆序 題目&#xff1a; 將一個英文語句以單詞為單位逆序排放。例如“I am a boy”&#xff0c;逆序排放后為“boy a am I”所有單詞之間用一個空格隔開&#xff0c;語句中除了英文字母外&#xff0c;不再包含其他字符 想法&#xff1a; 將輸入的字符串通過…

【2024最新華為OD-C/D卷試題匯總】[支持在線評測] 英文單詞聯想(100分) - 三語言AC題解(Python/Java/Cpp)

?? 大家好這里是清隆學長 ,一枚熱愛算法的程序員 ? 本系列打算持續跟新華為OD-C/D卷的三語言AC題解 ?? ACM銀牌??| 多次AK大廠筆試 | 編程一對一輔導 ?? 感謝大家的訂閱? 和 喜歡?? ??在線評測鏈接 https://app5938.acapp.acwing.com.cn/contest/2/problem/OD…

阿里云物聯網應用層開發:第二部分,云產品流轉

文章目錄 嗶哩嗶哩視頻教程1、云產品流轉概述2、我們需要創建多少個云產品流轉?3、阿里云物聯網平臺產品云流轉實現3-1 創建數據源3-2 創建數據目的3-2 創建解析器,并關聯數據、編寫腳本嗶哩嗶哩視頻教程 【阿里云物聯網綜合開發,STM32+ESP8266+微信小程序+web客戶端一篇教程…

自定義控件動畫篇(八)animateLayoutChanges與LayoutTransition的使用

在Android開發中&#xff0c;animateLayoutChanges 和 LayoutTransition 都是用來在布局改變時添加動畫效果的特性&#xff0c;但是它們的使用場景和方式有所不同。 animateLayoutChanges animateLayoutChanges 是一個布爾屬性&#xff0c;當它被設置為true時&#xff0c;會使…

jvm常見調優

FullGC的STW停頓時間長 單體應用一臺硬件上的jvm的部署策略 單獨的jvm管理堆內存 對于用戶停頓時間敏感的系統&#xff0c;并不是必須使用Shenandoah或者ZGC這些明確以控制延遲為目標的垃圾回收器才能解決問題&#xff08;當然&#xff0c;這是最好的方法&#xff09;&#…

centos7安裝寶塔面板

一、進入root模式 sudo su二、安裝寶塔面板 if [ -f /usr/bin/curl ];then curl -sSO https://download.bt.cn/install/install_panel.sh;else wget -O install_panel.sh https://download.bt.cn/install/install_panel.sh;fi;bash install_panel.sh ed8484bec