当前位置:   article > 正文

怎样用AIDL Service 传递复杂数据_aidl传输list

aidl传输list

大家都知道在Android中通过AIDL可以跨进程调用Service中的数据,网上也有很多实例,但是大部分实例都是关于基本数据类型的远程调用,很少讲到复杂数据的调用,今天我用一个例子来演示一下怎样用AIDL Service 传递复杂数据。

我们分2步开始:

第一步:部署我们的服务端,也就是Service端:

1:在Service端我先自定义2个类型:Person和Pet。因为我们需要跨进程传递Person对象和Pet对象,所以Person类和Pet类都必须实现Parcelable接口,并要求在实现类中定义一个名为CREATER,类型为Parcelable.creator的静态Field。

代码如下:

  1. package com.example.remoteservice;
  2. import android.os.Parcel;
  3. import android.os.Parcelable;
  4. public class Person implements Parcelable {
  5. int id;
  6. String name;
  7. String pass;
  8. public Person() {
  9. }
  10. public Person(int id, String name, String pass) {
  11. this.id = id;
  12. this.name = name;
  13. this.pass = pass;
  14. }
  15. @Override
  16. public boolean equals(Object o) {
  17. if (this == o) {
  18. return true;
  19. }
  20. if (o == null) {
  21. return false;
  22. }
  23. if (getClass() != o.getClass()) {
  24. return false;
  25. }
  26. Person other = (Person) o;
  27. if (name == null) {
  28. if (other.name != null) {
  29. return false;
  30. }
  31. } else if (!name.equals(other.name)) {
  32. return false;
  33. }
  34. if (pass == null) {
  35. if (other.pass != null) {
  36. return false;
  37. }
  38. } else if (!pass.equals(other.pass)) {
  39. return false;
  40. }
  41. return true;
  42. }
  43. @Override
  44. public int hashCode() {
  45. final int prime = 31;
  46. int result = 1;
  47. result = prime * result + (name == null ? 0 : name.hashCode());
  48. result = prime * result + (pass == null ? 0 : pass.hashCode());
  49. return result;
  50. }
  51. @Override
  52. public int describeContents() {
  53. return 0;
  54. }
  55. @Override
  56. public void writeToParcel(Parcel arg0, int arg1) {
  57. arg0.writeInt(id);
  58. arg0.writeString(name);
  59. arg0.writeString(pass);
  60. }
  61. public static final Parcelable.Creator<Person> CREATOR = new Creator<Person>() {
  62. @Override
  63. public Person createFromParcel(Parcel source) {
  64. return new Person(source.readInt(), source.readString(), source.readString());
  65. }
  66. @Override
  67. public Person[] newArray(int size) {
  68. return new Person[size];
  69. }
  70. };
  71. public int getId() {
  72. return id;
  73. }
  74. public void setId(int id) {
  75. this.id = id;
  76. }
  77. public String getName() {
  78. return name;
  79. }
  80. public void setName(String name) {
  81. this.name = name;
  82. }
  83. public String getPass() {
  84. return pass;
  85. }
  86. public void setPass(String pass) {
  87. this.pass = pass;
  88. }
  89. }

因为我们会对Person进行比较,所以在Person类中我重写了

public int hashCode() 和 public boolean equals(Object o)方法
  1. package com.example.remoteservice;
  2. import android.os.Parcel;
  3. import android.os.Parcelable;
  4. public class Pet implements Parcelable {
  5. String name;
  6. float weight;
  7. public Pet(String name, float weight) {
  8. this.name = name;
  9. this.weight = weight;
  10. }
  11. public String getName() {
  12. return name;
  13. }
  14. public void setName(String name) {
  15. this.name = name;
  16. }
  17. public float getWeight() {
  18. return weight;
  19. }
  20. public void setWeight(float weight) {
  21. this.weight = weight;
  22. }
  23. @Override
  24. public int describeContents() {
  25. return 1;
  26. }
  27. @Override
  28. public void writeToParcel(Parcel dest, int flags) {
  29. dest.writeString(name);
  30. dest.writeFloat(weight);
  31. }
  32. public static final Parcelable.Creator<Pet> CREATOR = new Creator<Pet>() {
  33. @Override
  34. public Pet createFromParcel(Parcel source) {
  35. return new Pet(source.readString(), source.readFloat());
  36. }
  37. @Override
  38. public Pet[] newArray(int size) {
  39. return new Pet[size];
  40. }
  41. };
  42. @Override
  43. public String toString() {
  44. return "name:" + this.name + ";weight:" + this.weight;
  45. }
  46. }

2:创建完自定义类型之后还需要用AIDL来定义它们,Person.aidl和Pet.aidl的代码如下:

Person.aidl

  1. package com.example.remoteservice;
  2. parcelable Person;
Pet.aidl
  1. package com.example.remoteservice;
  2. parcelable Pet;

3:完成1,2之后就可以使用AIDL定义通信接口了,在这里我定义一个IPet.aidl的接口,代码如下:

  1. package com.example.remoteservice; //必须导入包
  2. import com.example.remoteservice.Person; //指定自定义类的位置
  3. import com.example.remoteservice.Pet;
  4. interface IPet
  5. {
  6. List<Pet> getPets(in Person owner);//这里的in表示Person对象是输入的参数
  7. }

4:服务端的最后一步就是实现Service了,当然不要忘了注册Service,代码如下:

  1. package com.example.remoteservice;
  2. import com.example.remoteservice.IPet.Stub;
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import android.app.Service;
  8. import android.content.Intent;
  9. import android.os.IBinder;
  10. import android.os.RemoteException;
  11. import android.util.Log;
  12. public class RemoteService extends Service {
  13. private PetBinder petBinder;
  14. private static Map<Person, List<Pet>> pets = new HashMap<Person, List<Pet>>();
  15. static {
  16. ArrayList<Pet> list1 = new ArrayList<Pet>();
  17. list1.add(new Pet("candy", 2.2f));
  18. list1.add(new Pet("sandy", 4.2f));
  19. pets.put(new Person(1, "sun", "sun"), list1);
  20. ArrayList<Pet> list2 = new ArrayList<Pet>();
  21. list2.add(new Pet("moon", 5.2f));
  22. list2.add(new Pet("hony", 6.2f));
  23. pets.put(new Person(1, "csx", "csx"), list2);
  24. }
  25. public class PetBinder extends Stub {// 继承IPet接口中的Stub类,Stub类继承了Binder类,所有PetBinder也间接的继承了Binder类
  26. @Override
  27. public List<Pet> getPets(Person owner) throws RemoteException {
  28. return pets.get(owner);
  29. }
  30. }
  31. @Override
  32. public IBinder onBind(Intent intent) {
  33. Log.i("csx", "onBind");
  34. return petBinder;
  35. }
  36. @Override
  37. public void onCreate() {
  38. super.onCreate();
  39. Log.i("csx", "onCreate");
  40. petBinder = new PetBinder();// 实例化Binder
  41. }
  42. @Override
  43. public boolean onUnbind(Intent intent) {
  44. Log.i("csx", "onUnbind");
  45. return super.onUnbind(intent);
  46. }
  47. @Override
  48. public void onDestroy() {
  49. super.onDestroy();
  50. Log.i("csx", "onDestroy");
  51. }
  52. }

这是我Service端的部署情况(其中MainActivity可以不用去实现,因为我们只提供服务,没有窗口显示):

第二步:部署客户端:

1.在客户端新建一个包,命名需要和服务端放置aidl文件的包名相同(我这里是com.example.remoteservice),然后把服务端的Person.java,Pet.java,Person.aidl,Pet.aidl,IPet.aidl复制到这个包下面

2.在activity中绑定远程服务进行数据交换,layout布局和activity代码如下:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:paddingBottom="@dimen/activity_vertical_margin"
  6. android:paddingLeft="@dimen/activity_horizontal_margin"
  7. android:paddingRight="@dimen/activity_horizontal_margin"
  8. android:paddingTop="@dimen/activity_vertical_margin"
  9. tools:context="com.example.remoteclient.RemoteClient" >
  10. <LinearLayout
  11. android:layout_width="match_parent"
  12. android:layout_height="match_parent"
  13. android:orientation="vertical" >
  14. <LinearLayout
  15. android:layout_width="match_parent"
  16. android:layout_height="wrap_content"
  17. android:orientation="horizontal" >
  18. <EditText
  19. android:id="@+id/editText_person"
  20. android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:layout_gravity="bottom"
  23. android:ems="10" >
  24. </EditText>
  25. <Button
  26. android:id="@+id/button_ok"
  27. android:layout_width="wrap_content"
  28. android:layout_height="wrap_content"
  29. android:layout_gravity="bottom"
  30. android:text="确定" />
  31. </LinearLayout>
  32. <ListView
  33. android:id="@+id/listView_pet"
  34. android:layout_width="match_parent"
  35. android:layout_height="wrap_content" >
  36. </ListView>
  37. </LinearLayout>
  38. </RelativeLayout>

  1. package com.example.remoteclient;
  2. import android.app.Service;
  3. import android.content.ComponentName;
  4. import android.content.Intent;
  5. import android.content.ServiceConnection;
  6. import android.os.Bundle;
  7. import android.os.IBinder;
  8. import android.os.RemoteException;
  9. import android.support.v7.app.ActionBarActivity;
  10. import android.util.Log;
  11. import android.view.View;
  12. import android.view.View.OnClickListener;
  13. import android.widget.ArrayAdapter;
  14. import android.widget.Button;
  15. import android.widget.EditText;
  16. import android.widget.ListView;
  17. import com.example.remoteservice.IPet;
  18. import com.example.remoteservice.Person;
  19. import com.example.remoteservice.Pet;
  20. import java.util.List;
  21. public class RemoteClient extends ActionBarActivity {
  22. public static final String REMOTE_SERVICE_ACTION = "com.example.remoteservice.RemoteService.ACTION";
  23. EditText editText;
  24. Button button;
  25. ListView listView;
  26. IPet petService;// 声明IPet接口
  27. List<Pet> pets;
  28. ServiceConnection conn = new ServiceConnection() {
  29. @Override
  30. public void onServiceDisconnected(ComponentName name) {
  31. Log.i("csx", "onServiceDisconnected");
  32. conn = null;
  33. }
  34. @Override
  35. public void onServiceConnected(ComponentName name, IBinder service) {
  36. Log.i("csx", "onServiceConnected");
  37. petService = IPet.Stub.asInterface(service);// 通过远程服务的Binder实现接口
  38. }
  39. };
  40. @Override
  41. protected void onCreate(Bundle savedInstanceState) {
  42. super.onCreate(savedInstanceState);
  43. setContentView(R.layout.remote_client_layout);
  44. editText = (EditText) findViewById(R.id.editText_person);
  45. button = (Button) findViewById(R.id.button_ok);
  46. listView = (ListView) findViewById(R.id.listView_pet);
  47. Intent service = new Intent();
  48. service.setAction(REMOTE_SERVICE_ACTION);
  49. bindService(service, conn, Service.BIND_AUTO_CREATE);// 绑定远程服务
  50. button.setOnClickListener(new OnClickListener() {
  51. @Override
  52. public void onClick(View v) {
  53. String personName = editText.getText().toString();
  54. if (personName == null || personName.equals("")) {
  55. return;
  56. }
  57. try {
  58. pets = petService.getPets(new Person(1, personName, personName));// 调用远程service的getPets方法
  59. updataListView();
  60. } catch (RemoteException e) {
  61. e.printStackTrace();
  62. } catch (NullPointerException e) {
  63. e.printStackTrace();
  64. }
  65. }
  66. });
  67. }
  68. public void updataListView() {
  69. listView.setAdapter(null);
  70. if (pets == null || pets.isEmpty()) {
  71. return;
  72. }
  73. ArrayAdapter<Pet> adapter = new ArrayAdapter<Pet>(RemoteClient.this,
  74. android.R.layout.simple_list_item_1, pets);
  75. listView.setAdapter(adapter);
  76. }
  77. @Override
  78. protected void onDestroy() {
  79. unbindService(conn);// 解除绑定
  80. super.onDestroy();
  81. }
  82. }

到此为止所有的工作都完成了,下面我们看一下效果:我在编辑框中输入“csx”,点击确定,就会显示出服务端RemoteService中pets的相应数据。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/245321
推荐阅读
相关标签
  

闽ICP备14008679号