热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

详解Android进程间通信的几种实现方式

在AndroidSDK中提供了4种用于跨进程通讯的方式。这篇文章主要介绍了详解Android进程间通信的几种实现方式,有兴趣的可以了解一下。

一、概述

由于应用程序之间不能共享内存。在不同应用程序之间交互数据(跨进程通讯),在Android SDK中提供了4种用于跨进程通讯的方式。

这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和Service。其中Activity可以跨进程调用其他应用程序的Activity;Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),当然,也可以对其他应用程序的数据进行增、删、改操 作;Broadcast可以向android系统中所有应用程序发送广播,而需要跨进程通讯的应用程序可以监听这些广播;Service和Content Provider类似,也可以访问其他应用程序中的数据,但不同的是,Content Provider返回的是Cursor对象,而Service返回的是Java对象,这种可以跨进程通讯的服务叫AIDL服务。

 Activity

Activity的跨进程访问与进程内访问略有不同。虽然它们都需要Intent对象,但跨进程访问并不需要指定Context对象和Activity的 Class对象,而需要指定的是要访问的Activity所对应的Action(一个字符串)。有些Activity还需要指定一个Uri(通过 Intent构造方法的第2个参数指定)。

在android系统中有很多应用程序提供了可以跨进程访问的Activity,例如,下面的代码可以直接调用拨打电话的Activity。

Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:12345678" ); 
startActivity(callIntent);

Content Provider 

Android应用程序可以使用文件或SqlLite数据库来存储数据。Content Provider提供了一种在多个应用程序之间数据共享的方式(跨进程共享数据)。应用程序可以利用Content Provider完成下面的工作

1. 查询数据

2. 修改数据

3. 添加数据

4. 删除数据

虽然Content Provider也可以在同一个应用程序中被访问,但这么做并没有什么意义。Content Provider存在的目的向其他应用程序共享数据和允许其他应用程序对数据进行增、删、改操作。

Android系统本身提供了很多Content Provider,例如,音频、视频、联系人信息等等。我们可以通过这些Content Provider获得相关信息的列表。这些列表数据将以Cursor对象返回。因此,从Content Provider返回的数据是二维表的形式。

广播(Broadcast) 

广播是一种被动跨进程通讯的方式。当某个程序向系统发送广播时,其他的应用程序只能被动地接收广播数据。这就象电台进行广播一样,听众只能被动地收听,而不能主动与电台进行沟通。
在应用程序中发送广播比较简单。只需要调用sendBroadcast方法即可。该方法需要一个Intent对象。通过Intent对象可以发送需要广播的数据。

Service

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如下:

 
 
   
 
   
       
         
       
     
   
 
 

然后运行该Service所在的Project即可。

客户端代码如下:

注意客户端也要有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) { 
   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) { 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
  } 
  @Override 
  protected void onDestroy() { 
    super.onDestroy(); 
    unbindService(conn); 
  } 
} 

activity_main.xml的代码如下:

 
 
  

运行结果如下:

bubuko.com,布布扣

然后举一个稍微复杂一点的栗子,注意如果*.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.CreatorCREATOR=new Parcelable.Creator() { 
 
    @Override 
    public Room createFromParcel(Parcel source) { 
      return new Room(source); 
    } 
 
    @Override 
    public Room[] newArray(int size) { 
      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:\n"); 
    sb.append("RoomNum:"+roomNum+"\n"); 
    sb.append("RoomSpace:"+roomSpace+"\n"); 
    sb.append("HasAirConditioner:"+hasAirConditioner+"\n"); 
    sb.append("HasWifi:"+hasWifi+"\n"); 
    sb.append("Decorative Style:"+decorativeStyle); 
    return sb.toString(); 
     
  } 
   
  @Override 
  public int describeContents() { 
    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的代码不变,因而此处不再贴出。下面是客户端的代码:

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) { 
    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) { 
    resent. 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
  } 
  @Override 
  protected void onDestroy() { 
    super.onDestroy(); 
    unbindService(conn); 
  } 
} 

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

运行结果如下:

bubuko.com,布布扣

显然,客户端已经成功读取到服务信息。

注意,上面的所举的栗子其实不只是跨进程,还是跨应用。要注意的是,跨应用一定跨进程,但是跨进程不一定是跨应用。对于跨应用的情况,利用AIDL基本上是较好的解决了问题,但也只是“较好”而已,实际上并不完美,比如,如果要增加一个服务,如果利用AIDL的话,那么又要改写aidl文件,如果是涉及自定义对象,则还要增加自定义对象的声明,而且这种改变不只是Service端的改变,客户端也要跟着改变,显然这种解决方案不够优雅。

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

当然有,那就是利用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() { 
    showLog("onDestroy"); 
    super.onDestroy(); 
  } 
 
  @Override 
  public void onCreate() { 
    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); 
  } 
   
} 

客户端代码如下:

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) { 
  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) { 
   resent. 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
  } 
  @Override 
  protected void onDestroy() { 
    super.onDestroy(); 
  } 
} 

运行结果如下:

bubuko.com,布布扣

显然,此时客户端顺利获取了服务。

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

RoomService的代码如下:

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() { 
    showLog("onDestroy"); 
    super.onDestroy(); 
  } 
 
  @Override 
  public void onCreate() { 

    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); 
  } 
   
}

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) { 
   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) { 
   resent. 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
  } 
  @Override 
  protected void onDestroy() { 
    super.onDestroy(); 
  } 
} 

从打印的log可看出,客户端每调用一次Context.startService(Intent),Service就会重新执行一次onStartCommand---->onStart;但是使用AIDL的话,绑定服务之后,不会重复执行onStart,显然后者的代价更小。

Service:前台Service,像我们经常用的天气、音乐其实都利用了前台Service来实现

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • Servlet过滤器入门:实现与配置
    本文介绍如何在Java Web应用中实现和配置Servlet过滤器,通过实现`javax.servlet.Filter`接口来创建过滤器,并详细说明其在web.xml文件中的配置方法。 ... [详细]
  • 请看|间隔时间_Postgresql 主从复制 ... [详细]
  • MySQL锁机制详解
    本文深入探讨了MySQL中的锁机制,包括表级锁、行级锁以及元数据锁,通过实例详细解释了各种锁的工作原理及其应用场景。同时,文章还介绍了如何通过锁来优化数据库性能,避免常见的并发问题。 ... [详细]
  • 本文探讨了如何利用SqlDependency执行复杂的SQL查询,并确保在多线程环境下的安全性与效率。 ... [详细]
  • 深入解析Android中的SQLite数据库使用
    本文详细介绍了如何在Android应用中使用SQLite数据库进行数据存储。通过自定义类继承SQLiteOpenHelper,实现数据库的创建与版本管理,并提供了具体的学生信息管理示例代码。 ... [详细]
  • 本文探讨了Web开发与游戏开发之间的主要区别,旨在帮助开发者更好地理解两种开发领域的特性和需求。文章基于作者的实际经验和网络资料整理而成。 ... [详细]
  • 探讨HTML中的DIV样式难题
    本文深入分析了HTML中常见的DIV样式问题,并提供了有效的解决策略。适合所有对Web前端开发感兴趣的读者。 ... [详细]
  • 本文详细介绍了如何在Android应用中使用GridView组件以网格形式展示数据(如文本和图像)。通过行列布局,实现类似矩阵的数据展示效果。 ... [详细]
  • PHP 中 preg_match 函数的 isU 修饰符详解
    本文详细解析 PHP 中 preg_match 函数中 isU 修饰符的具体含义及其应用场景,帮助开发者更好地理解和使用正则表达式。 ... [详细]
  • 在使用Maven进行项目构建时,由于依赖库的下载速度慢常常让人感到沮丧,这直接影响了开发效率和学习热情。幸运的是,阿里云提供了一个快速的国内镜像服务,能够显著提升Maven项目的构建速度。 ... [详细]
  • 本文介绍了在Android项目中实现时间轴效果的方法,通过自定义ListView的Item布局和适配器逻辑,实现了动态显示和隐藏时间标签的功能。文中详细描述了布局文件、适配器代码以及时间格式化工具类的具体实现。 ... [详细]
  • 本文将带您了解Cocos家族的不同版本和分支,特别是Cocos Creator的发展历程及其核心特性,帮助初学者快速入门。 ... [详细]
  • 俗话说得好,“工欲善其事,必先利其器”。这句话不仅强调了工具的重要性,也提醒我们在任何项目开始前,准备合适的工具至关重要。本文将介绍几款C语言编程中常用的工具,帮助初学者更好地选择适合自己学习和工作的编程环境。 ... [详细]
  • 本文将详细介绍如何安装和使用 CactiEZ 的中文版本,帮助那些对英文界面不太熟悉的用户轻松掌握这一强大的网络监控工具。 ... [详细]
  • Win10 UWP 开发技巧:利用 XamlTreeDump 获取 XAML 元素树
    本文介绍如何在 Win10 UWP 开发中使用 XamlTreeDump 库来获取和转换 XAML 元素树为 JSON 字符串,这对于 UI 单元测试非常有用。 ... [详细]
author-avatar
mobiledu2502886985
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有