zoukankan      html  css  js  c++  java
  • Android中的跨进程通信方法实例及特点分析(一):AIDL Service

               转载请注明出处:http://blog.csdn.net/bettarwang/article/details/40947481

          近期有一个需求就是往程序中增加大数据的採集点,可是由于我们的Android程序包括两个进程,所以涉及到跨进程通信的问题。现将Android中的跨进程通信方式总结例如以下。

           Android中有4种跨进程通信方式,各自是利用AIDL Service、ContentProvider、Broadcast、Activity实现。

     1.利用AIDL Service实现跨进程通信

            这是我个人比較推崇的方式,由于它相比Broadcast而言,尽管实现上略微麻烦了一点。可是它的优势就是不会像广播那样在手机中的广播较多时会有明显的时延,甚至有广播发送不成功的情况出现。 

           注意普通的Service并不能实现跨进程操作,实际上普通的Service和它所在的应用处于同一个进程中,并且它也不会专门开一条新的线程,因此假设在普通的Service中实如今耗时的任务,须要新开线程。

           要实现跨进程通信,须要借助AIDL(Android Interface Definition Language)。Android中的跨进程服务事实上是採用C/S的架构。因而AIDL的目的就是实现通信接口。

          首先举一个简单的栗子。

          服务端代码例如以下:

          首先是aidl的代码:

    package com.android.service;
    
    interface IData
    {
        int getRoomNum();
    }

    RoomService的代码例如以下:

    package com.android.service;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    
    public class RoomService extends Service{
    
    	private IData.Stub mBinder=new IData.Stub() {
    		
    		@Override
    		public int getRoomNum() throws RemoteException {
    			 return 3008;
    		}
    	};
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		return mBinder;
    	}
    
    }
    AndroidManifest例如以下:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.android.aidlsampleservice"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="8"
            android:targetSdkVersion="17" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >      
            <service android:name="com.android.service.RoomService">
                <intent-filter>
                    <action android:name="com.aidl.service.room"/>
                </intent-filter>
            </service>
        </application>
    
    </manifest>
    然后执行该Service所在的Project就可以。

    client代码例如以下:

    注意client也要有aidl文件,所以最简单的办法就是将Service端中aidl所在的包直接复制过去。

    另外要注意的是在onDestroy中要解除和Service的绑定。

    MainActivity.java的代码例如以下:

    package com.example.aidlsampleclient;
    
    import com.android.service.IData;
    
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.util.Log;
    import android.view.Menu;
    import android.widget.Button;
    import android.widget.Toast;
    import android.view.View;
    
    public class MainActivity extends Activity implements View.OnClickListener{
    
    	
    	private static final String TAG="MainActivity";
    	private static final String ROOM_SERVICE_ACTION="com.aidl.service.room";
    	
    	private Button bindServiceButton;
    	private Button getServiceButton;
    	
    	
    	IData mData;
        
    	private ServiceConnection conn=new ServiceConnection()
    	{
    
    		@Override
    		public void onServiceConnected(ComponentName name, IBinder service) {
    		
    			Log.i(TAG,"----------------onServiceConnected--------");
    			mData=IData.Stub.asInterface(service);
    		}
    
    		@Override
    		public void onServiceDisconnected(ComponentName name) {
    		
    			Log.i(TAG,"----------------onServiceDisconnected-------------");
    			mData=null;
    			
    		}
    		
    	};
    	
    	private void initView()
    	{
    		bindServiceButton=(Button)findViewById(R.id.bindServiceButton);
    		getServiceButton=(Button)findViewById(R.id.getServiceButton);
    		bindServiceButton.setOnClickListener(this);
    		getServiceButton.setOnClickListener(this);
    	}
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		initView();
    	}
    	
    	@Override
    	public void onClick(View v) {
    		// TODO Auto-generated method stub
    		switch(v.getId())
    		{
    		case R.id.bindServiceButton:
    			bindService();
    			break;
    		case R.id.getServiceButton:
    			getService();	
    		     break;
    		default:
    			 break;
    		}
    	}
    	
    	
    	private void bindService()
    	{
    		Intent intent=new Intent();
    		intent.setAction(ROOM_SERVICE_ACTION);
    		bindService(intent,conn,BIND_AUTO_CREATE);
    	}
    	
    	private void getService()
    	{
    		try
    		{
    			if(mData!=null)
    			{
    				int roomNum=mData.getRoomNum();
    				showLongToast("RoomNum:"+roomNum);
    			}
    			
    		}
    		catch(RemoteException ex)
    		{
    			ex.printStackTrace();
    		}
    		
    	}
    	
    	private void showLongToast(String info)
    	{
    		Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();
    	}
    
    	@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;
    	}
    	@Override
    	protected void onDestroy() {
    		// TODO Auto-generated method stub
    		super.onDestroy();
    		unbindService(conn);
    	}
    }
    
    activity_main.xml的代码例如以下:

    <RelativeLayout 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: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/bindServiceButton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="BindService"
            />
        <Button
            android:id="@+id/getServiceButton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="GetService"
            android:layout_below="@id/bindServiceButton"
            />
           
    </RelativeLayout>
    执行结果例如以下:


          

           然后举一个略微复杂一点的栗子,注意假设*.aidl文件里含有自己定义的对象,那么该对象的类要实现Parcelable接口,而且要新建一个该类的aidl文件,否则会出现could not find import for class com.android.service.XX的错误。当中XX为类名。还是上面的栗子。可是aidl文件里加入了一些新的方法。仍以上面的RoomService为例。

         Service端的代码例如以下:

         Room类的代码为:

    package com.android.service;
    
    import android.os.Parcel;
    import android.os.Parcelable;
    
    public class Room implements Parcelable{
    
    	//房间号
    	private int roomNum;
    	//房间大小
    	private float roomSpace;
    	//是否有空调
    	private boolean hasAirConditioner;
    	//是否有Wifi
    	private boolean hasWifi;
    	//房间内的装饰风格
    	private String decorativeStyle;
    	
    	public static final Parcelable.Creator<Room>CREATOR=new Parcelable.Creator<Room>() {
    
    		@Override
    		public Room createFromParcel(Parcel source) {
    			return new Room(source);
    		}
    
    		@Override
    		public Room[] newArray(int size) {
    			// TODO Auto-generated method stub
    			return null;
    		}
    		
    	};
    	
    	public Room(int roomNum,float roomSpace,boolean hasAirConditioner,boolean hasWifi,String decorativeStyle)
    	{
    		this.roomNum=roomNum;
    		this.roomSpace=roomSpace;
    		this.hasAirConditioner=hasAirConditioner;
    		this.hasWifi=hasWifi;
    		this.decorativeStyle=decorativeStyle;
    	}
    	
    	private Room(Parcel source)
    	{
    		roomNum=source.readInt();
    		roomSpace=source.readFloat();
    		boolean[]tempArray=new boolean[2];
    		source.readBooleanArray(tempArray);
    	   hasAirConditioner=tempArray[0];
    	   hasWifi=tempArray[1];
    	   decorativeStyle=source.readString();	
    	}
    	
    	@Override
    	public String toString()
    	{
    		StringBuilder sb=new StringBuilder();
    		sb.append("Basic info of room is as follows:
    ");
    		sb.append("RoomNum:"+roomNum+"
    ");
    		sb.append("RoomSpace:"+roomSpace+"
    ");
    		sb.append("HasAirConditioner:"+hasAirConditioner+"
    ");
    		sb.append("HasWifi:"+hasWifi+"
    ");
    		sb.append("Decorative Style:"+decorativeStyle);
    		return sb.toString();
    		
    	}
    	
    	@Override
    	public int describeContents() {
    		// TODO Auto-generated method stub
    		return 0;
    	}
    
    	@Override
    	public void writeToParcel(Parcel dest,int flags) {
    		dest.writeInt(roomNum);
    		dest.writeFloat(roomSpace);
    		dest.writeBooleanArray(new boolean[]{hasAirConditioner,hasWifi});
    		dest.writeString(decorativeStyle);		
    	}
    
    }

    Room的声明为:

    package com.android.service;
    parcelable Room;

    IRoom.aidl的代码为:

    package com.android.service;
    import com.android.service.Room;
    
    interface IRoom
    {
      Room getRoom();
    }
    RoomService的代码为:

    package com.android.service;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    
    public class RoomService extends Service{
    
    	private IRoom.Stub mBinder=new IRoom.Stub() {
    		
    		@Override
    		public Room getRoom() throws RemoteException {
    			Room room=new Room(3008,23.5f,true,true,"IKEA");
    			return room;		
    		}
    	};
    	
    	@Override
    	public IBinder onBind(Intent intent) {
    		return mBinder;
    	}
    
    }
    
    因为AndroidManifest.xml的代码不变。因而此处不再贴出。以下是client的代码:

    package com.example.aidlsampleclient;
    import com.android.service.IRoom;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.util.Log;
    import android.view.Menu;
    import android.widget.Button;
    import android.widget.Toast;
    import android.view.View;
    
    public class MainActivity extends Activity implements View.OnClickListener{
    
    	
    	private static final String TAG="MainActivity";
    	//private static final String SERVICE_ACTION="com.aidl.service.data";
    	private static final String ROOM_SERVICE_ACTION="com.aidl.service.room";
    	
    	private Button bindServiceButton;
    	private Button getServiceButton;
    	
    	
    	IRoom mRoom;
        
    	private ServiceConnection conn=new ServiceConnection()
    	{
    
    		@Override
    		public void onServiceConnected(ComponentName name, IBinder service) {
    		
    			Log.i(TAG,"----------------onServiceConnected--------");
    			showLongToast("onServiceConnected");
    			mRoom=IRoom.Stub.asInterface(service);
    		}
    
    		@Override
    		public void onServiceDisconnected(ComponentName name) {
    		
    			Log.i(TAG,"----------------onServiceDisconnected-------------");
    			mRoom=null;
    			
    		}
    		
    	};
    	
    	private void initView()
    	{
    		bindServiceButton=(Button)findViewById(R.id.bindServiceButton);
    		getServiceButton=(Button)findViewById(R.id.getServiceButton);
    		bindServiceButton.setOnClickListener(this);
    		getServiceButton.setOnClickListener(this);
    	}
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		initView();
    	}
    	
    	@Override
    	public void onClick(View v) {
    		// TODO Auto-generated method stub
    		switch(v.getId())
    		{
    		case R.id.bindServiceButton:
    			bindService();
    			break;
    		case R.id.getServiceButton:
    			getService();	
    		     break;
    		default:
    			 break;
    		}
    	}
    	
    	
    	private void bindService()
    	{
    		Intent intent=new Intent();
    		intent.setAction(ROOM_SERVICE_ACTION);
    		bindService(intent,conn,BIND_AUTO_CREATE);
    	}
    	
    	private void getService()
    	{
    		if(mRoom!=null)
    		{
    			try
    			{
    				showLongToast(mRoom.getRoom().toString());
    			}
    			catch (RemoteException e) 
    			{
    				e.printStackTrace();
    			}
    		}
    
    	}
    	
    	private void showLongToast(String info)
    	{
    		Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();
    	}
    
    	@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;
    	}
    	@Override
    	protected void onDestroy() {
    		// TODO Auto-generated method stub
    		super.onDestroy();
    		unbindService(conn);
    	}
    }
    

    注意首先仍然是要将Room,IRoom的代码复制过去,否则会出错。

    执行结果例如以下:


    显然。client已经成功读取到服务信息。

    注意。上面的所举的栗子事实上不仅仅是跨进程。还是跨应用。要注意的是。跨应用一定跨进程。可是跨进程不一定是跨应用。

    对于跨应用的情况。利用AIDL基本上是较好的攻克了问题,但也仅仅是“较好”而已。实际上并不完美,比方。假设要添加一个服务,假设利用AIDL的话,那么又要改写aidl文件,假设是涉及自己定义对象,则还要添加自己定义对象的声明,并且这样的改变不仅仅是Service端的改变。client也要跟着改变,显然这样的解决方式不够优雅。

            那么。有没有更优雅的方法呢?

            当然有。那就是利用Service的onStartCommand(Intent intent, int flags, int startId)方法。

            服务端代码例如以下:

     

    package com.android.service;
    
    import android.app.Service;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.util.Log;
    import android.widget.Toast;
    
    public class RoomService extends Service{
    
    	private static final String TAG="RoomService";
    	private static final int CLEAN_SERVICE=0x1;
    	private static final int ORDER_SERVICE=0x2;
    	private static final int PACKAGE_SERVICE=0x3;
    	private static final String SERVICE_KEY="ServiceName";	
    	@Override
    	public void onStart(Intent intent, int startId) {
    	   showLog("onStart");
    	}
    
    	@Override
    	public int onStartCommand(Intent intent, int flags, int startId) {
    		//String action=intent.getAction();
    		Log.i(TAG,"onStartCommand");
    		
    		int actionFlag=intent.getIntExtra(SERVICE_KEY, -1);
    		switch(actionFlag)
    		{
    		case CLEAN_SERVICE:
    			showShortToast("Start Clean Service Right Now");
    			break;
    		case ORDER_SERVICE:
    			showShortToast("Start Order Service Right Now");
    			break;
    		case PACKAGE_SERVICE:
    			showShortToast("Start Package Service Right Now");
    			break;
    		default:
    			break;
    		}
    		return super.onStartCommand(intent, flags, startId);
    	}
    
        private void showLog(String info)
        {
        	Log.i(TAG,info);
        }
        
        private void showShortToast(String info)
        {
        	Toast.makeText(getBaseContext(), info, Toast.LENGTH_SHORT).show();
        }
    	@Override
    	public void onDestroy() {
    		// TODO Auto-generated method stub
    		showLog("onDestroy");
    		super.onDestroy();
    	}
    
    	@Override
    	public void onCreate() {
    		// TODO Auto-generated method stub
    		showLog("onCreate");
    		super.onCreate();
    	}
    
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		showLog("onBind");
    		return null;
    	}
    
    	@Override
    	public boolean onUnbind(Intent intent) {
    		showLog("onUnbind");
    		return super.onUnbind(intent);
    	}
    	
    }
    
    client代码例如以下:

    package com.example.aidlsampleclient;
    import com.android.service.IRoom;
    import com.android.service.RoomService;
    
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.util.Log;
    import android.view.Menu;
    import android.widget.Button;
    import android.widget.Toast;
    import android.view.View;
    
    public class MainActivity extends Activity implements View.OnClickListener{
    
    	private static final String TAG="MainActivity";
    	private static final String ROOM_SERVICE_ACTION="com.aidl.service.room";
    	
    	private static final int CLEAN_SERVICE=0x1;
    	private static final int ORDER_SERVICE=0x2;
    	private static final int PACKAGE_SERVICE=0x3;
    	
    	private static final String SERVICE_KEY="ServiceName";
    	
    	private Button cleanButton;
    	private Button orderButton;
    	private Button packageButton;
    	
    	private void initView()
    	{
    		cleanButton=(Button)findViewById(R.id.cleanButton);
    		orderButton=(Button)findViewById(R.id.orderButton);
    		packageButton=(Button)findViewById(R.id.packageButton);
    	
    		cleanButton.setOnClickListener(this);
    		orderButton.setOnClickListener(this);
    		packageButton.setOnClickListener(this);
    	}
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		initView();
    	}
    	
    	@Override
    	public void onClick(View v) {
    		// TODO Auto-generated method stub
    		switch(v.getId())
    		{
    		case R.id.cleanButton:
    		    cleanAction();
    		    break;
    		case R.id.orderButton:
    			orderAction();
    			break;
    		case R.id.packageButton:
    			packageAction();
    			break;
    		default:
    			 break;
    		}
    	}
    		
    	private void cleanAction()
    	{
    		startAction(ROOM_SERVICE_ACTION,CLEAN_SERVICE);
    	}
    	
    	private void orderAction()
    	{
    		startAction(ROOM_SERVICE_ACTION,ORDER_SERVICE);
    	}
    	
    	private void packageAction()
    	{
    		startAction(ROOM_SERVICE_ACTION,PACKAGE_SERVICE);
    	}
    	
    	private void startAction(String actionName,int serviceFlag)
    	{
    		//Intent intent=new Intent(this,RoomService.class);
    		Intent intent=new Intent();
    		intent.setAction(actionName);
    		intent.putExtra(SERVICE_KEY, serviceFlag);
    		this.startService(intent);
    	}
    	
    	private void showLongToast(String info)
    	{
    		Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();
    	}
    
    	@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;
    	}
    	@Override
    	protected void onDestroy() {
    		// TODO Auto-generated method stub
    		super.onDestroy();
    	}
    }
    
    执行结果例如以下:










    显然。此时client顺利获取了服务。

            上面举的是跨应用的样例。假设是在同一个应用的不同进程的话,则有更简单的实现方法。

            RoomService的代码例如以下:

    <span style="font-size:18px;">package com.android.service;
    
    import com.android.actions.Actions;
    
    import android.app.Service;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.util.Log;
    import android.widget.Toast;
    
    public class RoomService extends Service{
    
    	private static final String TAG="RoomService";
    	@Override
    	public void onStart(Intent intent, int startId) {
    	   showLog("onStart");
    	}
    
    	@Override
    	public int onStartCommand(Intent intent, int flags, int startId) {
    		//String action=intent.getAction();
    		Log.i(TAG,"onStartCommand");
    		String action=intent.getAction();
    		if(Actions.CLEAN_ACTION.equals(action))
    		{    
    			showShortToast("Start Clean Service Right Now");
    		}
    		else if(Actions.ORDER_ACTION.equals(action))
    		{
    			showShortToast("Start Order Service Right Now");
    		}
    		else if(Actions.PACKAGE_ACTION.equals(action))
    		{
    			showShortToast("Start Package Service Right Now");
    		}
    		else
    		{
    			showShortToast("Wrong action");
    		}
    		return super.onStartCommand(intent, flags, startId);
    	}
    
        private void showLog(String info)
        {
        	Log.i(TAG,info);
        }
        
        private void showShortToast(String info)
        {
        	Toast.makeText(getBaseContext(), info, Toast.LENGTH_SHORT).show();
        }
    	@Override
    	public void onDestroy() {
    		// TODO Auto-generated method stub
    		showLog("onDestroy");
    		super.onDestroy();
    	}
    
    	@Override
    	public void onCreate() {
    		// TODO Auto-generated method stub
    		showLog("onCreate");
    		super.onCreate();
    	}
    
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		showLog("onBind");
    		return null;
    	}
    
    	@Override
    	public boolean onUnbind(Intent intent) {
    		showLog("onUnbind");
    		return super.onUnbind(intent);
    	}
    	
    }</span>
    

            MainActivity的代码例如以下:

    package com.android.activity;
    import com.android.activity.R;
    import com.android.service.RoomService;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.Menu;
    import android.widget.Button;
    import android.widget.Toast;
    import android.view.View;
    import com.android.actions.Actions;
    
    public class MainActivity extends Activity implements View.OnClickListener{
    
    	private static final String TAG="MainActivity";
    
    	private static final String SERVICE_KEY="ServiceName";
    	
    	private Button cleanButton;
    	private Button orderButton;
    	private Button packageButton;
    	
    	private void initView()
    	{
    		cleanButton=(Button)findViewById(R.id.cleanButton);
    		orderButton=(Button)findViewById(R.id.orderButton);
    		packageButton=(Button)findViewById(R.id.packageButton);
    	
    		cleanButton.setOnClickListener(this);
    		orderButton.setOnClickListener(this);
    		packageButton.setOnClickListener(this);
    	}
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		initView();
    	}
    	
    	@Override
    	public void onClick(View v) {
    		// TODO Auto-generated method stub
    		switch(v.getId())
    		{
    		case R.id.cleanButton:
    		    cleanAction();
    		    break;
    		case R.id.orderButton:
    			orderAction();
    			break;
    		case R.id.packageButton:
    			packageAction();
    			break;
    		default:
    			 break;
    		}
    	}
    		
    	private void cleanAction()
    	{
    		startAction(Actions.CLEAN_ACTION);
    	}
    	
    	private void orderAction()
    	{
    		startAction(Actions.ORDER_ACTION);
    	}
    	
    	private void packageAction()
    	{
    		startAction(Actions.PACKAGE_ACTION);
    	}
    	
    	private void startAction(String actionName)
    	{
    		Intent intent=new Intent(this,RoomService.class);
    		intent.setAction(actionName);
    		this.startService(intent);
    	}
    	
    	private void showLongToast(String info)
    	{
    		Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();
    	}
    
    	@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;
    	}
    	@Override
    	protected void onDestroy() {
    		// TODO Auto-generated method stub
    		super.onDestroy();
    	}
    }
    
    执行结果同上。此处不再贴图。

    那AIDL还有存在的必要吗?当然有!最重要的一点是代价问题,从打印的log可看出,client每调用一次Context.startService(Intent),Service就会又一次运行一次onStartCommand---->onStart。而使用AIDL的话。绑定服务之后,不会反复运行onStart。显然后者的代价更小。

            最后再讲一个Service的重点应用:前台Service,像我们经经常使用的天气、音乐事实上都利用了前台Service来实现。         实例到明天再补上吧。  

           转载请注明出处:http://blog.csdn.net/bettarwang/article/details/40947481      




  • 相关阅读:
    AX2009 VS平台报表开发学习笔记(二)数据源
    字符集的问题
    php侧拉菜单,漂亮,可以向右或者向左展开,支持FF,IE
    ASP正则函数替换分页后的参数
    asp 图片正则 替换,替换前检查图片是不是本地地址的方法
    asp正则过滤重复字符串的代码
    PHP 正则 email语句详解
    签东软了
    东软医疗面试归来
    linux的svn co
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7055633.html
Copyright © 2011-2022 走看看