日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

安卓学习 之 Service服务(十)

發(fā)布時間:2024/2/28 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 安卓学习 之 Service服务(十) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

服務(Service)是 Android 中實現(xiàn)程序后臺運行的解決方案,它非常適合用于去執(zhí)行那些不需要和用戶交互而且還要求長期運行的任務。

一、多線程編程

先介紹一下四個組件:

  • Message
  • Message 是在線程之間傳遞的消息,它可以在內部攜帶少量的信息,用于在不同線程之間交換數(shù)據(jù)。上一小節(jié)中我們使用到了 Message 的 what 字段,除此之外還可以使用 arg1 和 arg2 字段來攜帶一些整型數(shù)據(jù),使用 obj 字段攜帶一個 Object 對象。

  • Handler
  • Handler 顧名思義也就是處理者的意思,它主要是用于發(fā)送和處理消息的。發(fā)送消息一般是使用 Handler 的 sendMessage()方法,而發(fā)出的消息經(jīng)過一系列地輾轉處理后, 最終會傳遞到 Handler 的 handleMessage()方法中。

  • MessageQueue
  • MessageQueue是消息隊列的意思,它主要用于存放所有通過 Handler 發(fā)送的消息。這部分消息會一直存在于消息隊列中,等待被處理。每個線程中只會有一個 MessageQueue 對象。

  • Looper
  • Looper 是每個線程中的 MessageQueue 的管家,調用 Looper 的 loop()方法后,就會進入到一個無限循環(huán)當中,然后每當發(fā)現(xiàn) MessageQueue 中存在一條消息,就會將它取出,并傳遞到 Handler 的 handleMessage()方法中。每個線程中也只會有一個 Looper 對象。

    public class MainActivity extends Activity implements OnClickListener { public static final int UPDATE_TEXT = 1;private TextView text; private Button changeText;private Handler handler = new Handler() {public void handleMessage(Message msg) { switch (msg.what) {case UPDATE_TEXT:// 在這里可以進行UI操作text.setText("Nice to meet you"); break;default:break;}}};@Overridepublic void onClick(View v) { switch (v.getId()) {case R.id.change_text:new Thread(new Runnable() { @Overridepublic void run() {Message message = new Message(); message.what = UPDATE_TEXT;handler.sendMessage(message); // 將Message對象發(fā)送出去}}).start(); break;default:break;} }

    使用 AsyncTask

    class DownloadTask extends AsyncTask<Void, Integer, Boolean> {@Overrideprotected void onPreExecute() {progressDialog.show(); // 顯示進度對話框}@Overrideprotected Boolean doInBackground(Void... params) {try {while (true) {int downloadPercent = doDownload(); // 這是一個虛構的方法publishProgress(downloadPercent);if (downloadPercent >= 100) {break;}}} catch (Exception e) {return false;}return true;}@Overrideprotected void onProgressUpdate(Integer... values) {// 在這里更新下載進度progressDialog.setMessage("Downloaded " + values[0] + "%");}@Overrideprotected void onPostExecute(Boolean result) {progressDialog.dismiss(); // 關閉進度對話框// 在這里提示下載結果if (result) {Toast.makeText(context, "Download succeeded", Toast.LENGTH_SHORT).show();} else {Toast.makeText(context, " Download failed", Toast.LENGTH_SHORT).show();}} }
  • 在 doInBackground()方法里去執(zhí)行具體的下載任務。這個方法里的代碼都是在子線程中運行的,因而不會影響到主線程的運行。注意這里虛構了一個doDownload()方法,這個方法用于計算當前的下載進度并返回。

  • 調用 publishProgress()方法并將當前的下載進度傳進來,這樣 onProgressUpdate()方法就會很快被調用,在這里就可以進行 UI 操作了。

  • 當下載完成后,doInBackground()方法會返回一個布爾型變量,這樣 onPostExecute()方法就會很快被調用,這個方法也是在主線程中運行的。然后在這里我們會根據(jù)下載的結果來彈出相應的 Toast 提示,從而完成整個 DownloadTask 任務。

  • 簡單來說,使用 AsyncTask 的訣竅就是,在 doInBackground()方法中去執(zhí)行具體的耗時任務,在 onProgressUpdate()方法中進行 UI 操作,在 onPostExecute()方法中執(zhí)行一些任務的收尾工作。

    二、服務的基本用法

  • 新建一個服務繼承Service類。
  • public class MyService extends Service {@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {super.onDestroy();} }

    其中 onCreate()方法會在服務創(chuàng)建的時候調用,onStartCommand()方法會在每次服務啟動的時候調用,onDestroy()方法會在服務銷毀的時候調用。onBind()方法目前暫時將它忽略掉。

  • 在AndroidManifest.xml注冊該服務(四大組件都需要注冊)
  • <service android:name=".MyService" > </service>
  • 啟動和停止服務
  • // 啟動服務 Intent startIntent = new Intent(this, MyService.class); startService(startIntent); // 停止服務 Intent stopIntent = new Intent(this, MyService.class); stopService(stopIntent);

    二、活動與服務之間的通信

    啟動服務之后,活動與服務無關。只是活動通知服務一下:你可以啟動了,具體做什么不知道,完成的如何也不知道。 那么如何讓活動與服務更緊密一些:那就要用上面的onbind方法了。

    目的:在 MyService 里提供一個下載功能,然后在活動中可以決定何時開始下載,以及隨時查看下載進度。

  • 首先要知道ServiceConnection這個類的onServiceConnected和onServiceDisconnected這兩個方法分別會在綁定服務和取消綁定服務的時候回調用。我們寫一個匿名內部類。
  • private ServiceConnection connection = new ServiceConnection() { @Overridepublic void onServiceDisconnected(ComponentName name) {}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) { } };

    可以看到onServiceConnected傳進一個Ibinder實例。

  • 我們創(chuàng)建一個Ibinder實例
  • private DownloaderBinder mBinder = new DownloaderBinder();class DownloaderBinder extends Binder{public void startDownload(){Log.d(TAG, "startDownload: ");}public int getProgress(){Log.d(TAG, "getProgress: ");return 0;}}
  • 重寫ServcieConnection的onServiceConnected方法,讓服務和活動連接時產(chǎn)生聯(lián)系。
  • public void onServiceConnected(ComponentName name, IBinder service) {downloaderBinder = (MyService.DownloaderBinder) service;downloaderBinder.startDownload();downloaderBinder.getProgress(); }

    三、服務的生命周期

    有onCreate、onStartCommand、onBind和onDestroy等方法都是在服務生命周期內可能調用的方法。

  • 任何位置調用startService方法,服務會啟動起來,并回調onStartCommand方法;若服務未曾創(chuàng)建,則onCreate會先于onStartCommand方法;服務啟動后會運行,直到onStopService或StopSelf方法被調用;

  • 還可以調用bindService來獲得服務持久連接,此時回調bind方法,若未創(chuàng)建過,則會先onCreate再onbind,onBind方法會返回IBinder對象實例。自由通信了已經(jīng)可以。

  • bindService綁定后用unbindService解綁,此時會調用onDestroy方法;startService啟動后會調用stopService來結束服務。若同時調用了startService,bindService兩個方法,則必須同時調用stopService和unbindservice才可會執(zhí)行onDestroy方法,因為android機制規(guī)定了服務被啟動和綁定之后,會一直處于運行狀態(tài)。

  • 四、服務的更多技巧

  • 使用前臺服務
  • 前臺服務與普通服務最大區(qū)別在于:他有一個正在運行的圖標在系統(tǒng)狀態(tài)欄顯示,下拉通知欄可看到更加詳細,類似通知。比 如:彩云天氣,后臺更新天氣數(shù)據(jù),在系統(tǒng)欄一直顯示當前天氣信息。

    與Notifiction比較類似,構建的notification并沒有使用NotificationManager顯示出來,而是調用startForeGround來使MyService變成一個前臺服務,并在系統(tǒng)狀態(tài)欄顯示處出來。

    @Override public void onCreate() {super.onCreate();Log.d(TAG, "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 contnet title").setContentText("This is contnet Text").setWhen(System.currentTimeMillis()).setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)).setContentIntent(pi).build();startForeground(1,notification); }
  • 使用IntentService
  • 服務默認在主線程中進行,若在服務中處理耗時邏輯,則很容易出現(xiàn)ANR。這是采用多線程編程技術,在服務的每個方法中開啟一個子線程去處理耗時邏輯。服務執(zhí)行完后自動停止,可以使用StopSelf方法。

    @Override public int onStartCommand(Intent intent, int flags, int startId) {Log.d(TAG, "onStartCommand executed ");new Thread(new Runnable() {@Overridepublic void run() {//處理具體邏輯//服務執(zhí)行完后自動停止,可以使用StopSelf方法stopSelf();}});return super.onStartCommand(intent, flags, startId); }

    IntentService主要用于解決程序員忘記開啟線程,或者忘記調用stopSelf()方法

    public class MyIntentService extends IntentService {protected void onHandleIntent(Intent intent) {//處理具體邏輯} }

    總結

    以上是生活随笔為你收集整理的安卓学习 之 Service服务(十)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。