09. Android基礎(chǔ)——服務(wù)

定義

  1. 服務(wù)(Service)
    1. Android中實(shí)現(xiàn)程序后臺(tái)運(yùn)行的解決方案
    2. 通常用于不需要和用戶交互,但是又要長期運(yùn)行的程序
    3. 服務(wù)的運(yùn)行不依賴于用戶界面
    4. 服務(wù)不是運(yùn)行在一個(gè)獨(dú)立的進(jìn)程中的,而是依賴于創(chuàng)建服務(wù)時(shí)所在的程序的進(jìn)程,當(dāng)它所屬的程序的進(jìn)程被終止,這個(gè)服務(wù)也就停止了
    5. 服務(wù)不會(huì)自動(dòng)開啟線程,所有的代碼默認(rèn)運(yùn)行在主線程中,為了避免線程阻塞,執(zhí)行具體任務(wù)的子線程需要手動(dòng)創(chuàng)建

Android中的多線程

基本用法

  1. 例子

    • 使用繼承的方法來創(chuàng)建線程和啟動(dòng)線程

      // 新建一個(gè)類,繼承Thread類來定義線程
      class MyThread extends Thread{
          @Override
          public void run(){
              
          }
      }
      
      // 啟動(dòng)線程
      MyThread myThread = new MyThread();
      myThread.start();
      
    • 使用實(shí)現(xiàn)接口的方法來創(chuàng)建線程和啟動(dòng)線程

      // 新建一個(gè)類,實(shí)現(xiàn)Runnable接口來定義線程
      class MyThread implements Runnable{
          @Override
          public void run(){
              
          }
      }
      
      
      // 啟動(dòng)線程
      MyThread myThread = new MyThread();
      new Thread(myThread).start();
      
    • 使用匿名類實(shí)現(xiàn)

      new Thread(new Runnable(){
          @Override
          public void run(){
              
          }
      }).start();
      

異步消息處理機(jī)制

  1. Android的UI也是線程不安全的,如果需要更新程序匯總的UI元素,必須在主線程中進(jìn)行,否則程序會(huì)崩潰
  2. 子線程中通常會(huì)執(zhí)行一些耗時(shí)任務(wù),Android提供了一套異步消息處理機(jī)制,從而可以在子線程中進(jìn)行UI操作
  3. Android中的異步消息處理主要由4個(gè)部分組成
    1. Message
      • 在線程之間傳遞消息,可以在內(nèi)部攜帶少量的信息
      • message.what:用戶自定義的消息代碼
      • message.arg1:傳遞的int類型的值1
      • message.arg2:傳遞的int類型的值2
      • message.obj:傳遞一個(gè)object對(duì)象
    2. Handler
      • 用于發(fā)送和處理消息
      • 調(diào)用Handler中的sendMessage()方法發(fā)送消息
      • 消息經(jīng)過處理之后傳遞到Handler的handleMessage()方法中
    3. MessageQueue
      • 每個(gè)線程中只有一個(gè)MessageQueue對(duì)象
      • 消息隊(duì)列,用于存放所有通過Handler發(fā)送的消息
      • 這些消息會(huì)一直存放在隊(duì)列中,直到被處理
    4. Looper
      • 每個(gè)線程中只有一個(gè)Looper對(duì)象
      • 管理MessageQueue
      • Looper的loop()方法會(huì)讓程序進(jìn)行循環(huán)中
      • 然后每當(dāng)MessageQueue中存在一條消息,就將消息取出來
      • 將消息傳遞給handleMessage()方法
  4. 異步消息處理流程
    1. 在主線程中創(chuàng)建Handler對(duì)象,并重寫handleMessage()方法
    2. 當(dāng)子線程中需要進(jìn)行某些操作的時(shí)候(比如修改UI),創(chuàng)建一個(gè)Message對(duì)象,通過Handler將這個(gè)消息發(fā)出去
    3. 這個(gè)消息會(huì)被添加到MessageQueue隊(duì)列中等待處理,同時(shí)Looper會(huì)一直嘗試從MessageQueue中取出等待處理的消息
    4. 消息被處理之后會(huì)發(fā)還到Handler中的handleMessage()方法。注意,因?yàn)镠andler在主線程中創(chuàng)建,所以handleMessage()方法在主線程中運(yùn)行

AsyncTask

  1. AsyncTask的原理也是異步消息處理機(jī)制,但是Android對(duì)它進(jìn)行了封裝

  2. AsyncTask是一個(gè)抽象類,需要?jiǎng)?chuàng)建一個(gè)子類去繼承它,可以指定三個(gè)泛型參數(shù)

    1. Params:執(zhí)行AsyncTask時(shí)傳入的參數(shù),用于在后臺(tái)任務(wù)中使用

    2. Progress:后臺(tái)執(zhí)行任務(wù)的時(shí)候,如果需要在界面上顯示當(dāng)前的進(jìn)度,就使用它來作為進(jìn)度單位

    3. Result:當(dāng)任務(wù)執(zhí)行完畢之后,如果需要對(duì)結(jié)果進(jìn)行返回,就使用它作為返回值的類型

    4. 例子

      class MyTask extends AsyncTask<Void,Integer,Boolean>{}
      
      • 第一個(gè)泛型參數(shù)指定為Viod,表示不需要傳入?yún)?shù)給后臺(tái)任務(wù)
      • 第二個(gè)泛型參數(shù)指定為Integer,表示使用整型數(shù)據(jù)作為進(jìn)度顯示的單位
      • 第三個(gè)泛型參數(shù)指定為Boolean,表示使用布爾型數(shù)據(jù)來反饋執(zhí)行結(jié)果
  3. 繼承AsyncTask之后需要重寫的方法

    1. onPreExecute()

      • 在后臺(tái)任務(wù)開始執(zhí)行之前調(diào)用
      • 用于執(zhí)行一些界面上的初始化操作
    2. doInBackground(Params)

      • 這個(gè)方法所有的代碼都在子線程中運(yùn)行,在這里處理耗時(shí)的任務(wù),任務(wù)完成之后通過return語句將任務(wù)執(zhí)行的結(jié)果返回
      • 如果AsyncTask第三個(gè)泛型參數(shù)指定為Void,就不需要返回任務(wù)執(zhí)行結(jié)果
    3. onProgressUpdate(Progress)

      • 在這個(gè)方法中可以對(duì)UI進(jìn)行操作,利用參數(shù)中的數(shù)值可以對(duì)界面元素進(jìn)行相應(yīng)的更新
      • 參數(shù)是后臺(tái)任務(wù)中傳遞過來的
    4. onPostExecute(Result)

      • 后臺(tái)任務(wù)執(zhí)行完畢,且通過return語句進(jìn)行返回時(shí),調(diào)用這個(gè)方法
      • 返回的數(shù)據(jù)會(huì)作為參數(shù)傳遞到這個(gè)方法中,可以利用返回的數(shù)據(jù)進(jìn)行UI操作
    5. 例子

      public class MyTask extends AsyncTask<Void,Integer,Boolean> {
          @Override
          protected void onPreExecute(){
              progressDialog.show();
          }
      
          @Override
          protected Boolean doInBackground(Void...params){
              // 在這里執(zhí)行具體的下載任務(wù),這個(gè)方法中的代碼都在子線程中運(yùn)行
              try{
                  while (true){
                      // doDownload()用于計(jì)算當(dāng)前的下載進(jìn)度并返回
                      int downloadPercent = doDownload();
                      
                      // 調(diào)用publishProgress()方法并將當(dāng)前的下載進(jìn)度傳進(jìn)來
                      publishProgress(downloadPercent);
                      if (downloadPercent >= 100){
                          break;
                      }
                  }
              } catch (Exception e){
                  e.printStackTrace();
              }
              return true;
          }
      
          @Override
          protected  void onProgressUpdate(Integer...values){
              progressDialog.setMessage("下載進(jìn)度+"+values[0]+"%");
          }
      
          @Override
          protected void onPostExecute(Boolean result){
              progressDialog.dismiss();// 關(guān)閉對(duì)話框
              if (result){
                  Toast.makeText(context, "下載完成", Toast.LENGTH_SHORT).show();
              } else {
                  Toast.makeText(context, "下載失敗", Toast.LENGTH_SHORT).show();
              }
          }
      }
      
      // 啟動(dòng)任務(wù)
      new MyTask().execute();
      
  4. 總結(jié)

    1. 在doInBackground()方法中執(zhí)行具體的耗時(shí)的任務(wù)(比如下載)
    2. 在onProgressUpdate()方法中進(jìn)行UI操作
    3. 在onPostExecute()方法中執(zhí)行收尾工作

服務(wù)的基本用法

定義一個(gè)服務(wù)

  1. 例子

    public class MyService extends Service {
        public MyService() {
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            throw new UnsupportedOperationException("Not yet implemented");
        }
    
    
        @Override
        // 在服務(wù)創(chuàng)建的時(shí)候調(diào)用
        public void onCreate(){
            super.onCreate();
        }
        @Override
        // 在每次服務(wù)啟動(dòng)的時(shí)候調(diào)用
        public int onStartCommand(Intent intent,int flags,int startId){
            return super.onStartCommand(intent,flags,startId);
        }
    
        @Override
        // 在服務(wù)銷毀的時(shí)候調(diào)用
        public void onDestroy(){
            super.onDestroy();
        }
    }
    
  2. 需要在AndroidManifest.xml中注冊

    <service
                android:name=".MyService"
                android:enabled="true"
                android:exported="true">
                
            </service>
    

啟動(dòng)服務(wù)與停止服務(wù)

  1. 借助Intent來啟動(dòng)和停止服務(wù)

  2. 例子

    1. 設(shè)置兩個(gè)Button按鈕來啟動(dòng)服務(wù)和停止服務(wù)

      public class MainActivity extends AppCompatActivity implements View.OnClickListener {
      
          @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);
          }
      
          @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;
                  default:
                      break;
              }
          }
      }
      
    2. 自定義MyService

      public class MyService extends Service {
          public MyService() {
          }
      
          @Override
          public IBinder onBind(Intent intent) {
              throw new UnsupportedOperationException("Not yet implemented");
          }
      
      
          @Override
          public void onCreate(){
              super.onCreate();
              Log.d("MyService","onCreate方法執(zhí)行了");
          }
          @Override
          public int onStartCommand(Intent intent,int flags,int startId){
      
              Log.d("MyService","onStartCommand方法執(zhí)行了");
              return super.onStartCommand(intent,flags,startId);
          }
      
          @Override
          public void onDestroy(){
              super.onDestroy();
              Log.d("MyService","onDestroy方法執(zhí)行了");
          }
      }
      

活動(dòng)和服務(wù)進(jìn)行通信

  1. 例子

    public class MyService extends Service {
        
        private DownloadBinder mBinder = new DownloadBinder();
        class DownloadBinder extends Binder{
            public void startDownload(){
                Log.d("MyService","開始下載");
            }
            
            public int getProgress(){
                Log.d("MyService","獲取進(jìn)度的方法執(zhí)行了");
                return 0;
            }
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        public MyService() {
        }
    }
    
    • 新建了一個(gè)DownloadBinder類,這個(gè)類繼承Binder
    • 這個(gè)類實(shí)現(xiàn)了兩個(gè)方法,開始下載和查看下載進(jìn)度
    • 最后在onBind()方法中返回這個(gè)實(shí)例
  2. 當(dāng)一個(gè)活動(dòng)和服務(wù)綁定了之后,就可以使用這個(gè)服務(wù)中Binder提供的方法了

    1. 例子

      public class MainActivity extends AppCompatActivity implements View.OnClickListener {
      
          private MyService.DownloadBinder downloadBinder;
          
          // 創(chuàng)建ServiceConnection的匿名類,重寫了兩個(gè)方法
          private ServiceConnection connection = new ServiceConnection() {
              
              @Override
              // 在活動(dòng)與服務(wù)綁定的時(shí)候調(diào)用
              public void onServiceConnected(ComponentName name, IBinder service) {
                  // 向下轉(zhuǎn)型得到DownloadBinder的實(shí)例
                  downloadBinder  = (MyService.DownloadBinder) service;
                  downloadBinder.startDownload();
                  downloadBinder.getProgress();
              }
      
              @Override
              // 在活動(dòng)與服務(wù)解綁的時(shí)候調(diào)用
              public void onServiceDisconnected(ComponentName name) {
      
              }
          };
          
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              Button bindService = (Button) findViewById(R.id.bind_service);
              Button unbindService = (Button) findViewById(R.id.unbind_service);
              
              bindService.setOnClickListener(this);
              unbindService.setOnClickListener(this);
      
          }
      
          @Override
          public void onClick(View v) {
              switch (v.getId()) {
                  case R.id.bind_service:
                      Intent bindIntent = new Intent(this,MyService.class);
                      // 使用bindService()方法將MainActivity和Myservice綁定
                      // 參數(shù)1:Intent對(duì)象,
                      // 參數(shù)2:ServiceConnection的實(shí)例
                      // 參數(shù)3:標(biāo)志位,這里的BIND_AUTO_CREATE表示活動(dòng)和服務(wù)綁定后自動(dòng)創(chuàng)建服務(wù)
                      bindService(bindIntent,connection,BIND_AUTO_CREATE);
                      break;
                  case R.id.unbind_service:
                      // 解除綁定
                      unbindService(connection);
                  default:
                      break;
              }
          }
      }
      
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容