天天看點

Service和Activity通訊的3種常用方式示例

一般的Android業務開發中,Service的使用十分常見。稍微複雜點的業務邏輯,都需要Serivice在執行某些耗時操作後通知Activity。總結常見的三種方法。

        分别是:(1)binder持有Activity的Handler對象,或者持有一個Activity的callbackInterface.

        (2)AIDL實作,完美支援IPC。

          (3)startService+broadcastReceiver實作。

          另外還有幾種不推薦的方式,都有很高的局限性。比如Service執行後的結果持久化,通過startActivity在目标Activity中的OnNewIntent()處理(需要Activity是單例的)。

         (1)Binder持有Activity的Handler,這裡推薦Handler弱引用Activity實作。

           關鍵代碼如下:           

public class WeakReferenceHandlerActivity extends Activity {
	private MyHandler mHandler;
	public static int FLAG = 10;
	public ProgressBar progressBar;
	private Button bindButton;
	private Button nextButton;
	private UseHandlerService.MyBinder myBinder;  
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.handler_layout);
		progressBar = (ProgressBar)this.findViewById(R.id.progress);
		bindButton = (Button)this.findViewById(R.id.bind);
		nextButton = (Button)this.findViewById(R.id.next);
		mHandler = new MyHandler(this);
		
		bindButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				bindService();
				Log.d("","startDownLoad() --> click");
			}
		});
		nextButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				startActivity(new Intent(WeakReferenceHandlerActivity.this,AndroidAidlActivity.class));
			}
		});
	}

	
	  
    private ServiceConnection connection = new ServiceConnection() {  
  
        @Override  
        public void onServiceDisconnected(ComponentName name) {  
        	
        }  
  
        @Override  
        public void onServiceConnected(ComponentName name, IBinder service) { 
        	Log.d("","startDownLoad() --> onbind");
            myBinder = (UseHandlerService.MyBinder) service;  
            myBinder.setCallBackHandler(mHandler);
            myBinder.startDownLoad();
            
        }  
    };  
	
    @Override
	protected void onResume() {
    	
		super.onResume();
	}
    
    @Override
	protected void onPause() {
    	unBindService();
		super.onPause();
	}
    
    public void bindService(){
    	Intent bindIntent = new Intent(this, UseHandlerService.class);  
        bindService(bindIntent, connection, BIND_AUTO_CREATE);  
    }
    
    public void unBindService(){
    	unbindService(connection);
    }
    
	@Override
	protected void onDestroy() {
		// Remove all Runnable and Message.
		mHandler.removeCallbacksAndMessages(null);

		super.onDestroy();
	}

	public MyHandler getHandler(){
		return mHandler;
	}
	
	public class MyHandler extends Handler {
		// WeakReference to the outer class's instance.
		private WeakReference<WeakReferenceHandlerActivity> mOuter;

		public MyHandler(WeakReferenceHandlerActivity activity) {
			mOuter = new WeakReference<WeakReferenceHandlerActivity>(activity);
		}

		@Override
		public void handleMessage(Message msg) {
			WeakReferenceHandlerActivity outer = mOuter.get();
			if (outer != null) {
				// Do something with outer as your wish.
				if(!outer.isFinishing()){
					int progress = msg.what;
					progressBar.setProgress(progress);
				}
			}
		}
	}
}
           
public class UseHandlerService extends Service{
	/**
	 * 進度條的最大值
	 */
	public static final int MAX_PROGRESS = 100; 
	/**
	 * 進度條的進度值
	 */
	private int progress = 0;
	/**
	 * 更新進度的回調接口
	 */
	private MyHandler myHandler;
	private MyBinder mBinder = new MyBinder();  
	private String TAG = "UseHandlerService";
	/**
	 * 注冊回調接口的方法,供外部調用
	 * @param onProgressListener
	 */
	public void setHandler(MyHandler handler) {
		myHandler = handler;
	}
	/**
	 * 增加get()方法,供Activity調用
	 * @return 下載下傳進度
	 */
	public int getProgress() {
		return progress;
	}
	@Override  
    public void onCreate() {  
        super.onCreate();  
        Log.d(TAG, "onCreate() executed");  
    }  
  
    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        Log.d(TAG, "onStartCommand() executed");  
        return super.onStartCommand(intent, flags, startId);  
    }  
  
    @Override  
    public void onDestroy() {  
        super.onDestroy();  
        Log.d(TAG, "onDestroy() executed");  
    }  

	/**
	 * 傳回一個Binder對象
	 */
	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}
	
	public class MyBinder extends Binder{
		/**
		 * 擷取目前Service的執行個體
		 * @return
		 */
		public UseHandlerService getService(){
			return UseHandlerService.this;
		}
		
		public void setCallBackHandler(MyHandler handler){
			myHandler = handler;
		}
		
		public void startDownLoad(){
			Log.d("","startDownLoad() inBinder-->");
			new Thread(new Runnable() {
				public void run() {
					while(progress < MAX_PROGRESS){
						progress += 5;
						Log.d("","startDownLoad() run-->");
						//進度發生變化通知調用方
						if(myHandler != null){
							myHandler.sendEmptyMessage(progress);
						}
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}).start();
		}
	}
}
           

弱引用的實作,是出于防止Service不銷毀,一直導緻目标Activity也不能會回收的考慮。

(2)AIDL實作,同樣還是進度條的UI更新。

public class AndroidAidlActivity extends Activity {
    /** Called when the activity is first created. */
	public static final int MAX_PROGRESS = 100; 
	/**
	 * 進度條的進度值
	 */
	private int progress = 0;
	public ProgressBar progressBar;
	private Button bindButton;

	private MyAIDLService mService;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.handler_layout);
        
        progressBar = (ProgressBar)this.findViewById(R.id.progress);
        bindButton = (Button)this.findViewById(R.id.bind);
		bindButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				bindService();
				Log.d("","startDownLoad() --> click");
			}
		});
		this.findViewById(R.id.next).setVisibility(View.GONE);
    }
    
    private ICallBack.Stub mCallback = new ICallBack.Stub() {
    	 
         @Override
         public void showResult(final int result) {
             Log.d("", "showresult -->" + result);
             progressBar.setProgress(result);
         }
    };
    
    private ServiceConnection connection = new ServiceConnection() {  
        @Override  
        public void onServiceDisconnected(ComponentName name) {  
        	mService = null;
        }  
        @Override  
        public void onServiceConnected(ComponentName name, IBinder service) { 
        	Log.d("","startDownLoad() --> onbind");
        	mService = MyAIDLService.Stub.asInterface(service);
        	try {
        	    mService.registerCallback(mCallback);
        	    mService.startDownload();
        	} catch (RemoteException e) {
        	    Log.e("", "", e);
        	}
            
        }  
    };  
	
    @Override
	protected void onResume() {
		super.onResume();
	}
    
    @Override
	protected void onPause() {
    	unBindService();
		super.onPause();
	}
    
    public void bindService(){
    	Intent bindIntent = new Intent(this, AidlService.class);  
        bindService(bindIntent, connection, BIND_AUTO_CREATE);  
    }
    
    public void unBindService(){
    	unbindService(connection);
    }
    
	@Override
	protected void onDestroy() {
		// Remove all Runnable and Message.
		super.onDestroy();
	}
	

}
public class AidlService extends Service {

	private RemoteCallbackList<ICallBack> mCallbacks = new RemoteCallbackList<ICallBack>();
	
		MyAIDLService.Stub mBinder = new Stub() {

			@Override
			public void registerCallback(ICallBack cb) throws RemoteException {
				if(cb != null) {
                    mCallbacks.register(cb);
				}
			}
			@Override
			public void unregisterCallback(ICallBack cb) throws RemoteException {
				if(cb != null) {
                    mCallbacks.unregister(cb);
				}
			}

			@Override
			public void startDownload() throws RemoteException {
				Log.d("","startDownLoad() inBinder-->");
				new Thread(new Runnable() {

					public void run() {
						while(progress < MAX_PROGRESS){
							progress += 5;
							Log.d("","startDownLoad() run-->");
							//進度發生變化通知調用方
							if(mHandler != null){
								//TODO
								mHandler.sendEmptyMessage(progress);
							}
							
							try {
								Thread.sleep(1000);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
						
					}
				}).start();
			}
		};
		/**
		 * 進度條的最大值
		 */
		public static final int MAX_PROGRESS = 100; 
		/**
		 * 進度條的進度值
		 */
		private int progress = 0;
		/**
		 * 更新進度的回調接口
		 */
		private String TAG = "UseHandlerService";
		/**
		 * 增加get()方法,供Activity調用
		 * @return 下載下傳進度
		 */
		public int getProgress() {
			return progress;
		}

		@Override  
	    public void onCreate() {  
	        super.onCreate();  
	        //mHandler.sendEmptyMessageDelayed(0, 1000);
	        Log.d(TAG, "onCreate() executed");  
	    }  
		private void callBack(Message msg) {
			int N = mCallbacks.beginBroadcast();
			try {
			    for (int i = 0; i < N; i++) {
			    	Log.d("","mCallbacks -->progress"+msg.what);
			        mCallbacks.getBroadcastItem(i).showResult(msg.what);
			    }
			} catch (RemoteException e) {
			      Log.e(TAG, "", e);
			}
			mCallbacks.finishBroadcast();
		}
			
		private Handler mHandler = new Handler() {
			 
			      @Override
			      public void handleMessage(Message msg) {
			           callBack(msg);
			           super.handleMessage(msg);
			      }
			};
	    @Override  
	    public int onStartCommand(Intent intent, int flags, int startId) {  
	        Log.d(TAG, "onStartCommand() executed");  
	        return super.onStartCommand(intent, flags, startId);  
	    }  
	  
	    @Override  
	    public void onDestroy() {  
	        super.onDestroy();  
	        Log.d(TAG, "onDestroy() executed");  
	    }  
		/**
		 * 傳回一個Binder對象
		 */
		@Override
		public IBinder onBind(Intent intent) {
			return mBinder;
		}
		

	}
還有兩個AIDL檔案
package com.banking.hello;

interface ICallBack {
    void showResult(int result);
} 

package com.banking.hello;
import com.banking.hello.ICallBack;
interface MyAIDLService {
	void registerCallback(ICallBack cb);
    void unregisterCallback(ICallBack cb);
    void startDownload();
}
           

這種方式,無論Service是否是remote,都可以實作高效率通訊。

(3)第三種通過Receiver非常簡單,就不上代碼了。

sendBroadCast,然後在Activity中注冊一個相對應的内部receiver接受就可以了.

檢視工程