定義
- 服務(wù)(Service)
- Android中實(shí)現(xiàn)程序后臺(tái)運(yùn)行的解決方案
- 通常用于不需要和用戶交互,但是又要長期運(yùn)行的程序
- 服務(wù)的運(yùn)行不依賴于用戶界面
- 服務(wù)不是運(yùn)行在一個(gè)獨(dú)立的進(jìn)程中的,而是依賴于創(chuàng)建服務(wù)時(shí)所在的程序的進(jìn)程,當(dāng)它所屬的程序的進(jìn)程被終止,這個(gè)服務(wù)也就停止了
- 服務(wù)不會(huì)自動(dòng)開啟線程,所有的代碼默認(rèn)運(yùn)行在主線程中,為了避免線程阻塞,執(zhí)行具體任務(wù)的子線程需要手動(dòng)創(chuàng)建
Android中的多線程
基本用法
-
例子
-
使用繼承的方法來創(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ī)制
- Android的UI也是線程不安全的,如果需要更新程序匯總的UI元素,必須在主線程中進(jìn)行,否則程序會(huì)崩潰
- 子線程中通常會(huì)執(zhí)行一些耗時(shí)任務(wù),Android提供了一套異步消息處理機(jī)制,從而可以在子線程中進(jìn)行UI操作
- Android中的異步消息處理主要由4個(gè)部分組成
- Message
- 在線程之間傳遞消息,可以在內(nèi)部攜帶少量的信息
- message.what:用戶自定義的消息代碼
- message.arg1:傳遞的int類型的值1
- message.arg2:傳遞的int類型的值2
- message.obj:傳遞一個(gè)object對(duì)象
- Handler
- 用于發(fā)送和處理消息
- 調(diào)用Handler中的sendMessage()方法發(fā)送消息
- 消息經(jīng)過處理之后傳遞到Handler的handleMessage()方法中
- MessageQueue
- 每個(gè)線程中只有一個(gè)MessageQueue對(duì)象
- 消息隊(duì)列,用于存放所有通過Handler發(fā)送的消息
- 這些消息會(huì)一直存放在隊(duì)列中,直到被處理
- Looper
- 每個(gè)線程中只有一個(gè)Looper對(duì)象
- 管理MessageQueue
- Looper的loop()方法會(huì)讓程序進(jìn)行循環(huán)中
- 然后每當(dāng)MessageQueue中存在一條消息,就將消息取出來
- 將消息傳遞給handleMessage()方法
- Message
- 異步消息處理流程
- 在主線程中創(chuàng)建Handler對(duì)象,并重寫handleMessage()方法
- 當(dāng)子線程中需要進(jìn)行某些操作的時(shí)候(比如修改UI),創(chuàng)建一個(gè)Message對(duì)象,通過Handler將這個(gè)消息發(fā)出去
- 這個(gè)消息會(huì)被添加到MessageQueue隊(duì)列中等待處理,同時(shí)Looper會(huì)一直嘗試從MessageQueue中取出等待處理的消息
- 消息被處理之后會(huì)發(fā)還到Handler中的handleMessage()方法。注意,因?yàn)镠andler在主線程中創(chuàng)建,所以handleMessage()方法在主線程中運(yùn)行
AsyncTask
AsyncTask的原理也是異步消息處理機(jī)制,但是Android對(duì)它進(jìn)行了封裝
-
AsyncTask是一個(gè)抽象類,需要?jiǎng)?chuàng)建一個(gè)子類去繼承它,可以指定三個(gè)泛型參數(shù)
Params:執(zhí)行AsyncTask時(shí)傳入的參數(shù),用于在后臺(tái)任務(wù)中使用
Progress:后臺(tái)執(zhí)行任務(wù)的時(shí)候,如果需要在界面上顯示當(dāng)前的進(jìn)度,就使用它來作為進(jìn)度單位
Result:當(dāng)任務(wù)執(zhí)行完畢之后,如果需要對(duì)結(jié)果進(jìn)行返回,就使用它作為返回值的類型
-
例子
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é)果
-
繼承AsyncTask之后需要重寫的方法
-
onPreExecute()
- 在后臺(tái)任務(wù)開始執(zhí)行之前調(diào)用
- 用于執(zhí)行一些界面上的初始化操作
-
doInBackground(Params)
- 這個(gè)方法所有的代碼都在子線程中運(yùn)行,在這里處理耗時(shí)的任務(wù),任務(wù)完成之后通過return語句將任務(wù)執(zhí)行的結(jié)果返回
- 如果AsyncTask第三個(gè)泛型參數(shù)指定為Void,就不需要返回任務(wù)執(zhí)行結(jié)果
-
onProgressUpdate(Progress)
- 在這個(gè)方法中可以對(duì)UI進(jìn)行操作,利用參數(shù)中的數(shù)值可以對(duì)界面元素進(jìn)行相應(yīng)的更新
- 參數(shù)是后臺(tái)任務(wù)中傳遞過來的
-
onPostExecute(Result)
- 后臺(tái)任務(wù)執(zhí)行完畢,且通過return語句進(jìn)行返回時(shí),調(diào)用這個(gè)方法
- 返回的數(shù)據(jù)會(huì)作為參數(shù)傳遞到這個(gè)方法中,可以利用返回的數(shù)據(jù)進(jìn)行UI操作
-
例子
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();
-
-
總結(jié)
- 在doInBackground()方法中執(zhí)行具體的耗時(shí)的任務(wù)(比如下載)
- 在onProgressUpdate()方法中進(jìn)行UI操作
- 在onPostExecute()方法中執(zhí)行收尾工作
服務(wù)的基本用法
定義一個(gè)服務(wù)
-
例子
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(); } } -
需要在AndroidManifest.xml中注冊
<service android:name=".MyService" android:enabled="true" android:exported="true"> </service>
啟動(dòng)服務(wù)與停止服務(wù)
借助Intent來啟動(dòng)和停止服務(wù)
-
例子
-
設(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; } } } -
自定義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)行通信
-
例子
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í)例
-
當(dāng)一個(gè)活動(dòng)和服務(wù)綁定了之后,就可以使用這個(gè)服務(wù)中Binder提供的方法了
-
例子
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; } } }
-