因爲項目須要,咱們有時候須要在service中處理耗時操做,而後將結果發送給activity以更新狀態。一般狀況下,咱們只須要在一個service與一個activity之間通訊,一般這種狀況下,咱們使用最多的是經過回調接口。具體作法是在service中定義一個接口,在activity中實現該接口,並經過bindservice來傳入。實現方式很簡單,在此再也不贅述。java
當須要將service中的結果一次發送給多個activity時,咱們又該如何實現呢?通過多個項目的積累,總結了三種實現的方式。分別是回調接口、廣播接收者和觀察者模式。android
1.回調接口的方式,與單個service與單個activity通訊相似,只是將service中的接口變爲接口的集合,每一個須要通訊的activity都實現接口,而後在獲取結果後,循環調用集合中的實現類,來與多個activity進行通訊,代碼以下:app
Service類:異步
package com.example.servicecallback; import java.util.ArrayList; import java.util.List; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.util.Log; public class ContentService extends Service { //回調接口的集合 private List<Callback> list; @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return new LocalBinder(); } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); list = new ArrayList<Callback>(); } public final class LocalBinder extends Binder { public ContentService getService() { return ContentService.this; } } /** * 回調接口 * @author Ivan Xu * */ public interface Callback { public void getPerson(Person person); } /** * 往回調接口集合中添加一個實現類 * @param callback */ public void addCallback(Callback callback) { list.add(callback); } public void asyncSendPerson(final String name) { // 休息5秒,模擬異步任務 new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } handler.sendMessage(handler.obtainMessage(0, name)); } }).start(); } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub String name = (String) msg.obj; Log.i("ContentService", "---name-->" + name); Person person = new Person(); person.setName(name); Log.i("ContentService", "---list.size()-->" + list.size()); Log.i("ContentService", "---person-->" + person.toString()); //遍歷集合,通知全部的實現類,即activity for (int i = 0; i < list.size(); i++) { list.get(i).getPerson(person); } } }; }
第一個activity:async
package com.example.servicecallback; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; import com.example.servicecallback.ContentService.Callback; import com.example.servicecallback.ContentService.LocalBinder; public class MainActivity extends Activity implements Callback { private MyServiceConn conn; private ContentService service; private TextView mContent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); conn=new MyServiceConn(); bindService(new Intent(this, ContentService.class), conn, BIND_AUTO_CREATE); mContent = (TextView) findViewById(R.id.content); this.findViewById(R.id.button1).setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub startActivity(new Intent(MainActivity.this, OtherActivity.class)); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } public class MyServiceConn implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder binder) { service = ((LocalBinder) binder).getService(); //將當前activity添加到接口集合中 service.addCallback(MainActivity.this); } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub service = null; } } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); unbindService(conn); } /** * 獲取回調的內容,更新UI */ @Override public void getPerson(Person person) { // TODO Auto-generated method stub mContent.setText(person.toString()); } }
第二個activity:ide
package com.example.servicecallback; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import com.example.servicecallback.ContentService.Callback; import com.example.servicecallback.ContentService.LocalBinder; import com.example.servicecallback.MainActivity.MyServiceConn; public class OtherActivity extends Activity implements Callback { private ContentService service; private TextView mContent; private Button mSubmit; private EditText mEditText; private ServiceConnection conn; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.other); mEditText = (EditText) findViewById(R.id.edittext); mSubmit = (Button) findViewById(R.id.button1); mContent = (TextView) findViewById(R.id.content); mSubmit.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub String name = mEditText.getText().toString(); service.asyncSendPerson(name); } }); conn=new MyServiceConn(); bindService(new Intent(OtherActivity.this, ContentService.class), conn, BIND_AUTO_CREATE); } public final class MyServiceConn implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder binder) { // TODO Auto-generated method stub service = ((LocalBinder) binder).getService(); //將當前activity添加到接口集合中 service.addCallback(OtherActivity.this); } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub service = null; } } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); unbindService(conn); } /** * 獲取回調的內容,更新UI */ @Override public void getPerson(Person person) { // TODO Auto-generated method stub mContent.setText(person.toString()); } }
2.經過廣播接收者,在service中執行完耗時操做後,將結果以廣播的形式發送,在全部的activity中註冊廣播,接收到結果後更新UI,這種方式比較簡單,也是筆者比較推薦的方式。由於耗時的操做結果不須要以handler的方式發送到主線程,能夠直接在子線程中發送廣播,接收者始終運行在主線程中。代碼以下:佈局
Service類:this
package com.example.servicecallback; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; public class ContentService extends Service { @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return new LocalBinder(); } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); } public final class LocalBinder extends Binder { public ContentService getService() { return ContentService.this; } } public void asyncSendPerson(final String name) { // 休息5秒,模擬異步任務 new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } //能夠在子線程中直接發送廣播 sendContentBroadcast(name); } }).start(); } /** * 發送廣播 * @param name */ protected void sendContentBroadcast(String name) { // TODO Auto-generated method stub Intent intent=new Intent(); intent.setAction("com.example.servicecallback.content"); intent.putExtra("name", name); sendBroadcast(intent); } }
第一個activity:spa
package com.example.servicecallback; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; public class MainActivity extends Activity { private MyServiceConn conn; private TextView mContent; private ContentReceiver mReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); conn = new MyServiceConn(); bindService(new Intent(this, ContentService.class), conn, BIND_AUTO_CREATE); mContent = (TextView) findViewById(R.id.content); this.findViewById(R.id.button1).setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub startActivity(new Intent(MainActivity.this, OtherActivity.class)); } }); doRegisterReceiver(); } /** * 註冊廣播接收者 */ private void doRegisterReceiver() { mReceiver=new ContentReceiver(); IntentFilter filter = new IntentFilter( "com.example.servicecallback.content"); registerReceiver(mReceiver, filter); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } public class MyServiceConn implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder binder) { // service = ((LocalBinder) binder).getService(); } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub // service = null; } } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); unbindService(conn); if (mReceiver!=null) { unregisterReceiver(mReceiver); } } public class ContentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String name = intent.getStringExtra("name"); Person person = new Person(); person.setName(name); mContent.setText(person.toString()); } } }
另外一個activity:線程
package com.example.servicecallback; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import com.example.servicecallback.ContentService.LocalBinder; public class OtherActivity extends Activity { private ContentService service; private TextView mContent; private Button mSubmit; private EditText mEditText; private ServiceConnection conn; private ContentReceiver mReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.other); mEditText = (EditText) findViewById(R.id.edittext); mSubmit = (Button) findViewById(R.id.button1); mContent = (TextView) findViewById(R.id.content); mSubmit.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String name = mEditText.getText().toString(); service.asyncSendPerson(name); } }); conn=new MyServiceConn(); bindService(new Intent(OtherActivity.this, ContentService.class), conn, BIND_AUTO_CREATE); doRegisterReceiver(); } private void doRegisterReceiver() { mReceiver=new ContentReceiver(); IntentFilter filter = new IntentFilter( "com.example.servicecallback.content"); registerReceiver(mReceiver, filter); } public final class MyServiceConn implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder binder) { service = ((LocalBinder) binder).getService(); } @Override public void onServiceDisconnected(ComponentName name) { service = null; } } @Override protected void onDestroy() { super.onDestroy(); unbindService(conn); if (mReceiver!=null) { unregisterReceiver(mReceiver); } } public class ContentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String name = intent.getStringExtra("name"); Person person = new Person(); person.setName(name); mContent.setText(person.toString()); } } }
3.使用觀察者模式,service爲被觀察者,全部的activity爲觀察者,當service中的內容發生改變時,通知全部的activity來更新,代碼以下:
Service類:
package com.example.servicecallback; import java.util.Observable; import java.util.Observer; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Message; public class ContentService extends Service { //被觀察者 private MyObservable mObservable; @Override public IBinder onBind(Intent arg0) { return new LocalBinder(); } @Override public void onCreate() { super.onCreate(); mObservable = new MyObservable(); } public final class LocalBinder extends Binder { public ContentService getService() { return ContentService.this; } } public void asyncSendPerson(final String name) { // 休息5秒,模擬異步任務 new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } handler.sendMessage(handler.obtainMessage(0, name)); } }).start(); } /** * 添加觀察者 * @param observer */ public void addObserver(Observer observer) { mObservable.addObserver(observer); } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { String name = (String) msg.obj; Person person = new Person(); person.setName(name); //通知更新 mObservable.notifyChanged(person); } }; public class MyObservable extends Observable { public void notifyChanged(Object object) { this.setChanged(); this.notifyObservers(object); } } }
第一個activity:
package com.example.servicecallback; import java.util.Observable; import java.util.Observer; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; import com.example.servicecallback.ContentService.LocalBinder; public class MainActivity extends Activity implements Observer { private MyServiceConn conn; private TextView mContent; private ContentService mService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); conn = new MyServiceConn(); bindService(new Intent(this, ContentService.class), conn, BIND_AUTO_CREATE); mContent = (TextView) findViewById(R.id.content); this.findViewById(R.id.button1).setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this, OtherActivity.class)); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } public class MyServiceConn implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder binder) { mService = ((LocalBinder) binder).getService(); //將當前activity添加爲觀察者 mService.addObserver(MainActivity.this); } @Override public void onServiceDisconnected(ComponentName name) { mService = null; } } @Override protected void onDestroy() { super.onDestroy(); unbindService(conn); } //更新UI @Override public void update(Observable observable, Object data) { Person person = (Person) data; mContent.setText(person.toString()); } }
第二個activity:
package com.example.servicecallback; import java.util.Observable; import java.util.Observer; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import com.example.servicecallback.ContentService.LocalBinder; public class OtherActivity extends Activity implements Observer { private ContentService service; private TextView mContent; private Button mSubmit; private EditText mEditText; private ServiceConnection conn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.other); mEditText = (EditText) findViewById(R.id.edittext); mSubmit = (Button) findViewById(R.id.button1); mContent = (TextView) findViewById(R.id.content); mSubmit.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String name = mEditText.getText().toString(); service.asyncSendPerson(name); } }); conn = new MyServiceConn(); bindService(new Intent(OtherActivity.this, ContentService.class), conn, BIND_AUTO_CREATE); } public final class MyServiceConn implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder binder) { service = ((LocalBinder) binder).getService(); //將當前activity添加爲觀察者 service.addObserver(OtherActivity.this); } @Override public void onServiceDisconnected(ComponentName name) { service = null; } } @Override protected void onDestroy() { super.onDestroy(); unbindService(conn); } //更新UI @Override public void update(Observable observable, Object data) { // TODO Auto-generated method stub Person person=(Person) data; mContent.setText(person.toString()); } }
附上其餘相關代碼,三種方式都同樣:
Person類:
package com.example.servicecallback; public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person [name=" + name + "]"; } }
MainActiivty的佈局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="next" /> <TextView android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello_world" /> </LinearLayout>
OtherActivity的佈局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <EditText android:id="@+id/edittext" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="submit" /> <TextView android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="content" /> </LinearLayout>
因爲筆者的水平有限,若有錯漏,請各位留言指正,感激涕零!
以上雖有借鑑別人的思想,可是源代碼均爲原創。請尊重筆者的勞動成果。若是轉載,請註明出處,謝謝!
全文完