安卓開發 探究服務
前言:
關於安卓開發的筆記,其實基本都是我復現一行程式碼中的程式碼,並加上我自己的理解並解說的,也就是自己記錄著玩玩的,有問題歡迎評論區指正。
0x01 簡介
服務service是安卓裡面的四大元件之一,它的作用就是可以在應用程式關閉時,還可以繼續執行,比如我們平常電腦或手機聽歌的時候,我們會先開啟
音樂軟體,播放音樂後,切換別的應用,幹活去了對吧,但是我們在切換應用的時候,按道理應用這時候是已經掛在後臺了,但是音樂還是在正常播放的
也就是服務是支援應用程式在後臺正常執行的手段。
0x02 安卓多執行緒程式設計
至於為什麼先寫多執行緒,一個是書上是這順序,還有一個原因就是在於服務的幹事的地方,基本都在子執行緒裡面乾的,而服務並不是自己建立子程序的,
這需要我們在服務內部程式碼中去實現的,管他呢,都得學2333
安卓多執行緒和java的多執行緒差不多的,也都是三種方式
1.繼承Thread類,重寫run方法,然後建立對應的執行緒物件,呼叫start()方法,啟動執行緒
class OneThread extends Thread{ public void run() { Log.d("YenKoc", "重寫"); } }
OneThread one=new OneThread();
one.start();
2.實現Runnable介面,重寫run方法,建立對應的例項,然後再新建一個Thread物件,將上面的例項傳入Thread的構造方法中去,再呼叫start()
class OneThread implements Runnable{ public void run() { } } OneThread one =new OneThread(); new Thread(one).start();
3.匿名類建立子執行緒的方式
new Thread(new Runnable(){ public void run() { } }).start()
這種是是最簡單省事的,也是用的多的
然後在子執行緒中是無法更新UI的,這裡書裡也提供了一個簡單的案例,我就不提出來了,就是新建一個佈局,然後設定一個按鈕,一點就新建子執行緒去改變文字框的內容
由於子執行緒中無法更新ui,也就是會出現程式崩潰的情況,這裡就提出另一種完美解決安卓子程序更新ui的操作,安卓提供了一套訊息處理機制,其實之前在app啟動的原始碼中
也看到了訊息機制looper等,通過發訊號的模式去啟動的,這是題外話,這塊我也好久沒看了,又忘了233
這裡通過例項來看
package com.example.servicetest; import androidx.appcompat.app.AppCompatActivity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.net.IpSecManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import java.nio.BufferUnderflowException; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private TextView text; public static final int UPDATE_TEXT=1; private Handler handler=new Handler(){ public void handleMessage(Message msg){ switch (msg.what) { case UPDATE_TEXT: text.setText("Nice to meet you"); break; default: break; } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button changeText=(Button)findViewById(R.id.change_text); changeText.setOnClickListener(this); } public void onClick(View v) { switch (v.getId()) { case R.id.change_text: new Thread(new Runnable() { @Override public void run() { Message message=new Message(); message.what=1; handler.sendMessage(message); } }).start(); default: } } }
新建一個handler物件,並重寫了handlerMessage方法,裡面主要是根據訊息中的what欄位來選擇不同的處理方式,
然後在點選按鈕後,實際上是通過建立子程序,然後在子程序中,傳送了一個訊息給主執行緒handler,然後由主線
程來更新ui,這種非同步訊息處理機制,太酷了233,想當於領導在子執行緒裡面指揮,小弟在主執行緒裡面幹活。
至於原理也挺簡單當,看圖
message:字面意思,作為通訊用的
handler: 用來處理訊息的,要重寫handleMessage方法
MessageQueue:訊息佇列,因為訊息有先後順序的,相當於訊息容器,把訊息都裝到裡面
looper:訊息佇列的管家,一旦執行會輪詢訊息佇列,看看裡面是否有訊息,如果有就傳送,沒有的話就阻塞
之前使用的runOnUiThread其實就是上面那套的封裝,所以很香,所以那裡面是可以對ui操作的
0x02 服務
終於到服務了。。
package com.example.servicetest; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class MyService extends Service { public MyService() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } //服務建立的時候呼叫 public void onCreate() { super.onCreate(); } //服務每次啟動時被呼叫 public int onStartCommand(Intent intent,int flags,int startId) { return super.onStartCommand(intent,flags,startId); } public void onDestroy() { super.onDestroy(); } }
新建一個service類,然後重寫onCreate()方法,onStartCommand()方法(主要邏輯是寫到這裡),onDestroy()方法,
2.服務的啟動和停止,元件之間的啟動都是通過intent物件來啟動的
package com.example.servicetest; import androidx.appcompat.app.AppCompatActivity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.net.IpSecManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; import java.nio.BufferUnderflowException; 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); } 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; } } }
然後在MyService類改下程式碼
package com.example.servicetest; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class MyService extends Service { public MyService() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } //服務建立的時候呼叫 public void onCreate() { super.onCreate(); Log.d("MyService", "onCreate executed"); } //服務每次啟動時被呼叫 public int onStartCommand(Intent intent,int flags,int startId) { Log.d("MyService", "onStartCommand: executed"); return super.onStartCommand(intent,flags,startId); } public void onDestroy() { super.onDestroy(); Log.d("MyService", "onDestroy: executed"); } }
3.活動與服務之間的通訊,因為之前這種方式都是活動啟動完服務之後,就不管不顧了,無法知道服務具體邏輯是什麼,也控制不了,所以安卓想讓活動和服務緊密一點,所以提出了Binder機制
未完待續