サービス初体験


このセクションの概要

さて、最初の 3 つのセクションで Android のアクティビティについて学習してきましたが、きっと役に立つと思います。 このセクションの冒頭では、Android の 2 番目のコンポーネントである Service (サービス) について学び続けます。 さて、さっそくこのセクションを始めましょう!


1. スレッドに関連する概念

サービスの学習を始める前に、まずスレッドの概念をいくつか理解しましょう。

1) 関連概念:

  • プログラム: 特定のタスク
  • プロセス
  • を完了するために、特定の言語で書かれた命令のセット(静的コードのセット)。システムのスケジューリングとリソース割り当ての 独立した単位 であるプログラム を実行すると、オペレーティング システムは プロセスごとにメモリ空間を割り当ててください。プログラムは動的に順次実行され、コードのロードと実行が行われます。 完全なプロセスが実行されました!
  • スレッド: プロセスよりも小さい実行単位。各プロセスには複数のスレッドが存在する場合があります。スレッドはプログラムによって管理されます。システムのスケジュール! マルチスレッドの理解: 複数の命令を並列実行し、スケジューリングアルゴリズムに従ってそれぞれに
  • CPUタイムスライス
  • を割り当てる 実際にスレッドはタイムシェアリングで実行されますが、切り替え時間が非常に短く、ユーザーは「同時に」感じます。 2) スレッドのライフサイクル:

3) スレッドを作成する 3 つの方法: 1.png

Thread クラスを継承する

    Runnable インターフェイスを実装します
  1. Callable インターフェイスを実装する
  2. 2 で作成したスレッドを使用している場合は、
    new Thread(myThread).start();
    のように直接開始できます。多くの場合、次のような書き方で匿名クラスを使用します:
    new Thread(new Runnable(){
         public void run();
             }).start();
  3. 2. サービスとスレッドの違い
実際には、この 2 つの間にはあまり関係がありませんが、多くの友人がこの 2 つを混同することがよくあります。 スレッドとは、プログラム実行の最小単位であり、CPU 割り当ての基本単位です。 サービスは Android が提供するコンポーネントであり、バックグラウンドでの長時間の維持を可能にする最も一般的なものです。 使い方はポーリング操作です!または、バックグラウンドでアップデートをダウンロードするなど、バックグラウンドで何かを実行したい場合もあります。 これら 2 つの概念を混同しないように注意してください。

3. サービスのライフサイクル図


4. ライフサイクル分析

さて、上の図のライフサイクルから、Android ではサービスを使用する 2 つの方法があることがわかります。

1)StartService() はサービスを開始します
2)BindService() はサービスを開始します
PS: サービスを開始した後、サービスをバインドする別の方法もあります。


1) 関連メソッドの詳細な説明:

  • onCreate(): このメソッドは、サービスが初めて作成された直後にコールバックされ、このメソッドはライフサイクル全体を通じて使用されます。 順番に呼び出されるだけです!
  • onDestory(): このメソッドは、サービスが閉じられたときに呼び戻されます。このメソッドは 1 回だけ呼び出されます。
  • onStartCommand(intent,flag,startId): 初期バージョンは onStart(intent,startId)、 クライアントが startService(Intent) メソッドを呼び出すと、StartService メソッドを複数回呼び出すことができます。 ただし、新しい Service オブジェクトは作成されませんが、以前に生成された Service オブジェクトは引き続き再利用されますが、コールバックは続行されます。 onStartCommand() メソッド!
  • IBinder onOnbind(intent): このメソッドは Service によって実装される必要があるメソッドです。 IBinder オブジェクト、アプリはこのオブジェクトを通じて Service コンポーネントと通信します。
  • onUnbind(intent): サービスにバインドされているすべてのクライアントが切断されると、このメソッドが呼び戻されます。

2) StartServiceはServiceを開始します

最初の起動ではServiceインスタンスを作成し、onCreate()メソッドとonStartCommand()メソッドを順番に呼び出します。 実行状態に入り、StartService を再度呼び出してサービスを開始しても、新しい Service オブジェクトは作成されません。 システムは、以前に作成された Service オブジェクトを直接再利用し、その onStartCommand() メソッドを呼び出します。
しかし、そのような Service は呼び出し元との必要な接続を持たない、つまり、呼び出し元がそのライフサイクルを終了すると、 ただし、stopService が呼び出されない限り、サービスは実行され続けます
何度サービスが開始されても、サービスを停止するには StopService を 1 回呼び出すだけです


3) BindService が Service を開始します

bindService を初めて使用して Service をバインドすると、システムは Service インスタンスをインスタンス化し、その onCreate() メソッドと onBind() メソッドを呼び出し、その後呼び出し元を呼び出します。 IBinder を渡すことができ、Service は相互作用しました。bindService を使用して Service を再度バインドする場合、システムは新しい Service インスタンスを作成せず、追加された他のクライアントに IBinder オブジェクトを直接渡すだけです。後で!
サービスからバインドを解除する場合は、 unbindService() を呼び出すだけでよく、そのときに onUnbind メソッドと onDestory メソッドが呼び出されます。これは、複数のクライアントが同じ Service にバインドされている場合のクライアントの状況です。詳細は以下の通り クライアントはサービスとの対話を完了すると、 unbindService() メソッドを呼び出してバインドを解除します。すべてのクライアントがサービスからバインド解除されると、システムはサービスを破棄します。 (サービスが startService() メソッドによって開始されていない限り)
また、上記の状況とは異なり、bindService モードの Service は呼び出し元に関連付けられており、次のように理解できます。 「ロープ上のバッタ」、彼らは一緒に死にたいです。bindService の後、呼び出し元が破棄されると、サービスはすぐに終了します。 、int flags)
service: このインテントを通じて開始されるサービスを指定します
conn: ServiceConnection オブジェクト、ユーザーは訪問者とサービスの間の接続を監視します。 接続が成功すると、オブジェクトの onServiceConnected(ComponentName,IBinder) メソッドがコールバックされます。 本サービスが存在するホストが異常終了等により終了した場合、本サービスは訪問者との接続を切断されます。 接続時に
onServiceDisconnected(CompanentName) メソッドを呼び出しても、unBindService() メソッドを通じてアクティブに切断しても、上記のメソッドは呼び出されません!flags:
バインド時に Service を自動的に作成するかどうかを指定します (サービスにまだ作成されていません)、 パラメータは 0 (自動作成なし)、BIND_AUTO_CREATE (自動作成) です


4) StartService がサービスを開始すると、bindService がバインドされます。

サービスが StartService() を通じてクライアントによって開始された場合、そのサービスは他のクライアントによって開始されます。 次に、bindService() を呼び出してサービスにバインドし、次に unbindService() を呼び出してバインドを解除し、最後に Service にバインドするために bindingService() が呼び出された場合、この時点でトリガーされるライフサイクル メソッドは次のとおりです:
onCreate( )->onStartCommand( )->onBind( )->onUnbind( )->onRebind ( )
追記:前提条件: onUnbind() メソッドは true を返します。 ここで混乱する読者もいるかもしれません。unbindService を呼び出した後に Service を呼び出すべきではないでしょうか。 実際、これは、この Service が StartService メソッドによって開始されるためです。 したがって、バインドを解除するために onUnbind() メソッドを呼び出しても、サービスは終了しません。
結論: 開始されたサービスをバインドするために bindingService を使用する場合は、すでに開始されているサービスに注意してください。 システムは、サービスの内部 IBinder オブジェクトをアクティビティに渡すだけであり、サービスのライフサイクルは転送しません。 これはアクティビティにバインドされているため、バインドを解除するために unBindService() メソッドが呼び出されても、サービスは破棄されません。


5. ライフサイクルの検証

次に、ライフサイクルを検証するためのコードを作成します:

1) サービスを開始するための StartService の呼び出しシーケンスを検証します

まず、サービスをカスタマイズし、関連する印刷検証メソッドを書き直します。 logcat:

TestService1.java

public class TestService1 extends Service {
private Final String TAG = "TestService1"
//実装する必要があるメソッド
@Override
public IBinder onBind(Intenttent) {
Log.i(TAG, "onBind メソッドが呼び出されます!");
return null;
}

//サービスの作成時に呼び出されます
@Override
public void onCreate() {
reate メソッドが呼び出されます!"); super.onCreate( ; d メソッドはCall! ");
super.onDestroy();
}
}

AndroidManifest.xmlでサービス登録が完了します


<!-- Service コンポーネントを構成し、同時にアクションを構成します -->
<service android:name=".TestService1"> example.service.TEST_SERVICE1"/>
クリックイベント内の Service( ) と stopService( )

public class MainActivity extends Activity {
private Button start;

@Override
protected void onCreate(Bundle SavedInstanceState) {
超。 OnCreate(SavedinstanceState); ,同様にIntentプロパティ
final Intent intent = new Intent();
intent.setAction("com.jay.example.service.TEST_SERVICE1");
//は两个按钮设置点击イベント個別にサービスを停止します
start.setOnClickListener(new OnClickListener() startService(意図);
            }
});  

stop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
stopService(目的);

}
});  
}
}


操作のスクリーンショット:

3.jpg

クリックしてサービスを開始:

4.jpg

お腹いっぱい食べて何もすることがなくなったら、さらに数回クリックしてください:

5.jpg

最後にクリックしてサービスを停止します:

6.jpg

結果分析:

上記の実行結果から、ライフサイクル図で説明されている内容を確認できます。 さらに、onBind() メソッドが呼び出されないことがわかりました。また、サービスを複数回クリックして開始しても、onStartCommand が繰り返し呼び出されるだけです。 メソッド! サービスを何度開始しても、stopService はサービスを停止します


2) BindService がサービスを開始する順序を確認します:

コードを書き始める前に、最初にいくつかのことを理解する必要があります。 1 つ目は、最初の大きな図の下にある Context の bindingService メソッドです:

  • ServiceConnection オブジェクト: 訪問者とサービスの間の接続を監視します。接続が成功した場合は、コールバックします。 onServiceConnected()、異常終了またはその他の理由によりサービスが訪問者から切断された場合 接続すると、onServiceDisconnected メソッドがコールバックされます。unBindService() を呼び出しても、このメソッドは呼び出されません。onServiceConnected メソッドには、バインドされた Service を実装できる IBinder オブジェクトがあります。 Service クラスを開発するときは、デフォルトで IBinder onBind() メソッドを実装する必要があります。 IBinder オブジェクトは ServiceConnection オブジェクトの onServiceConnected パラメーターに渡され、次のことが可能になります。 ここで、この IBinder を通じてサービスと通信します
概要:

ステップ 1:
カスタム Service で Binder を継承し、独自の IBinder オブジェクトを実装しますステップ 2:
onBind() メソッドを通じて戻ります。 IBinder オブジェクトステップ 3:
Service をバインドするクラスで ServiceConnection オブジェクトを定義し、2 つのメソッドをオーバーライドします。 onServiceConnected と onDisconnected!次に、IBinder によって渡されたパラメーターを直接読み取るだけです さて、次のステップは、タイミングを確認するためのサービスを定義することです。 次に、BindService の使用法とメソッド呼び出しプロセスを示します。コードは比較的単純なので説明しません

TestService2.java:

public class TestService2 extends Service {
private Final String TAG = "TestService2";
private boolean quit;

//onBinder メソッドによって返されるオブジェクトを定義する
private MyBinder binding = new MyBinder(); Public Class MyBinder EXTENDS BINDER {
Public Int GetCount () {
Return Count; C iBinder Onbind (Intent Intent ) {
Log.i(TAG, "onBind メソッドが呼び出されました!"); Create() {
super.onCreate( ); T LOG.I (tag, "Oncreate メソッドが呼び出されます!");
// カウントの値を動的に変更するスレッドを作成します
new thread () {
awile (! Quit)
{
{
Thread.sleep(1000);
Public Boolean Onbind (Intent Intent) {
Log.i (タグ、「Onbind メソッドが呼び出されました!」);
public void onDestroy () {
super.ondestroy ();
this.quit = true;
log.i (タグ、「onDestroyed メソッドが呼び出された!」) { T Log.i (タグ、「onrebind メソッドが呼び出された!」);AndroidManifestのサービスコンポーネントを登録します

MainActivity.java:

public class MainActivity extends Activity {

private Button btnbind;
private Button btnstatus; // 開始された Service の IBinder オブジェクトも定義されます
TestService2.MyBinder バインダー; ServiceConnection conn = new ServiceConnection() {
System.out.println("-----サービスが切断されました ---------- "); ("--- ---- サービスが接続されました ----------- ");
Binder = (TestService2.myBinder) service; State) {p Super.Oncreate (Savedinstancestate );レイアウト.activity_main);
btnbind = (ボタン) findViewById(R.id.btnbind);
btnstatus = (ボタン) findViewById(R.id.btnstatus);        最終的なインテント intent = 新しいインテント();  
intent.setAction("com.jay.example.service.TEST_SERVICE2");  
btnbind.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//绑定service
bindService(intent, conn, Service.BIND_AUTO_CREATE);
}
});  

btncancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//サービス解除绑定
unbindService(conn);
}
});  

btnstatus.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "サービスの数の範囲:"
+バインダー.getCount(), Toast.LENGTH_SHORT).show();

クリックしてロック サービス:

ロックをクリックし続ける: 変化なし7.jpg

8.jpgGet現在の Service のステータス:

9.jpgUnbind:

もう一度結び付ける場合 設定直後にアクティビティを閉じるとエラーが報告されます。 その後、onUnbind メソッドと onDestory メソッドが自動的に呼び出されます。 10.jpg

上記の実行結果は、ライフサイクル図で次のことを確認します:

11.jpgBindService を使用してサービスをバインドし、onCreate()、onBind() メソッドを順番に呼び出します。 onBind() メソッドでカスタム IBinder オブジェクトを返してから呼び出すことができます。 このメソッドではServiceConnectionのonServiceConnected()メソッドを取得できます。 関連する操作を実行するための IBinder オブジェクトは、サービスがバインドされていないときに自動的に呼び出されます。 もちろん、onUnbind メソッドと onDestroyed メソッドは、複数のクライアントがバインドされている場合はすべてブロックを解除する必要があります。 バインディングのみが onDestoryed メソッドを呼び出して破棄します。