您的位置:首页 > 移动开发 > Android开发

Android中Parcelable接口跨进程传递复杂数据的应用

2015-04-30 11:15 661 查看
在前面的一篇文章<基于Android应用开发的跨进程通信实现(IPC)>介绍了通过跨进程实现基本数值类型(String)的传递,但是有的时候,需要跨进程实现传递相对较复杂的数据(比如图片之类的资源),而不仅仅是基本数据。那么,如何实现复杂数据跨进程的传递使用呢?这时候就不得不Parcelable接口搬出来了,假设我们需要跨进程的数据都包装在一个我们自定义的类里面,那么这个类就需要实现Parcelable这个接口了;

下面就以一个Demo来说明如何通过实现Parcelable这个接口实现传递复杂数据;

这个Demo的效果如下:




实现效果:在编辑框中输入相应的姓名(这些姓名要对应服务端中保存的用户信息姓名),点击按钮,将会得到相应的用户信息(姓名、手机号、头像),这些用户信息都是来自与客户端不在同一个进程的服务端的;

这个Demo包括两个应用程序:

1. 服务端应用程序,它的文件组成结构如下:




2.客户端应用程序,它的文件组成结构如下:




通过上面的服务端和客户端应用程序的文件结构可知,它们都共同有Person.java、IMyService.aidl、Person.aidl等文件;

当然通过之前的<基于Android应用开发的跨进程通信实现(IPC)>的介绍可知,要想实现两个应用程序之间跨进程调用,两个应用程序必须共同拥有aidl文件。

下面将介绍这些文件的实现:

1. Person.java:

Person类相当于一个包装用户信息数据的javaBean,该类实现Parcelable接口,是实现跨进程传递复杂数据的自定义类,代码实现如下:

[java] view
plaincopy

package com.feixun.hu.ipc.service;



import java.util.Map;



import android.graphics.Bitmap;

import android.graphics.drawable.Drawable;

import android.os.Parcel;

import android.os.Parcelable;



public class Person implements Parcelable

{



/*picture集合保存的是头像的Bitmap

* 注:此处不能是Drawable,Parcel是不能跨进程传递Drawable类型的,Bitmap类型是可以的

*/

private Map<String, Bitmap> picture;



private String name;

private String phone;



public Person(String name, String phone, Map<String, Bitmap> picture)

{

this.name = name;

this.phone = phone;

this.picture = picture;

}



public Map<String, Bitmap> getPictures() {

return picture;

}



public void setPictures(Map<String, Bitmap> picture) {

this.picture = picture;

}



public String getName() {

return name;

}



public void setName(String name) {

this.name = name;

}



public String getPhone() {

return phone;

}



public void setPhone(String phone) {

this.phone = phone;

}



@Override

public int describeContents()

{

// TODO Auto-generated method stub

return 0;

}



//实现Parcel接口必须覆盖实现的方法

@Override

public void writeToParcel(Parcel dest, int flags)

{

// TODO Auto-generated method stub

/*将Person的成员写入Parcel,

* 注:Parcel中的数据是按顺序写入和读取的,即先被写入的就会先被读取出来

*/

dest.writeString(name);

dest.writeString(phone);

dest.writeMap(picture);

}



//该静态域是必须要有的,而且名字必须是CREATOR,否则会出错

public static final Parcelable.Creator<Person> CREATOR =

new Parcelable.Creator<Person>()

{



@Override

public Person createFromParcel(Parcel source)

{

// TODO Auto-generated method stub

//从Parcel读取通过writeToParcel方法写入的Person的相关成员信息



String name = source.readString();

String phone = source.readString();

Map<String, Bitmap> picture = source.readHashMap(new ClassLoader()

{

});



//更加读取到的信息,创建返回Person对象

return new Person(name, phone, picture);

}



@Override

public Person[] newArray(int size)

{

// TODO Auto-generated method stub

//返回Person对象数组

return new Person[size];

}

};

}

2. Person.aidl:

Person作为实现跨进程传递复杂数据的类必须要创建一个对应的aidl文件对其进行声明,内容如下:

parcelable Person;

3. IMyService.aidl:

该文件和之前的<基于Android应用开发的跨进程通信实现(IPC)>文章中介绍的IMyService.aidl文件的作用一样,是实现跨进程的重要文件实现,内容如下:

package com.feixun.hu.ipc.service;

import com.feixun.hu.ipc.service.Person;



interface IMyService

{

Person getPerson(String name);

}

IMyService.aidl文件会在应用程序的gen目录中生成对应的IMyService.java文件;

以上这些文件时服务端和客户端必须共同拥有的,服务端实现将用户数据信息保存在客户端的Person对象,而客户端通过跨进程通信(IPC)获取得到服务端保存的那些用户信息数据,然后通过ListView不断添加显示出来;

服务端应用程序的代码实现如下:

IpcService.java

[java] view
plaincopy

package com.feixun.hu.ipc.service;



import java.util.HashMap;

import java.util.Map;



import android.app.Service;

import android.content.Intent;

import android.graphics.Bitmap;

import android.graphics.drawable.BitmapDrawable;

import android.os.IBinder;

import android.os.RemoteException;

public class IpcService extends Service

{

//创建一个用于保存Person对象信息的HashMap对象

private Map<String, Person> mPersons = new HashMap<String, Person>();

//创建一个用于保存头像图片的HashMap对象

private Map<String, Bitmap> mPictures = new HashMap<String, Bitmap>(); ;



private ServiceBinder mServiceBinder;



private String[] names;

private String[] phones;

private Bitmap[] pictures;



/*初始化用户的姓名、手机号、头像(注:当我们在客户端要检索这些用户信息时,

* 输入的用户名必须是names数组中的任意一个)

*/

private void init()

{

names = new String[]{"steven", "lisa", "rose", "sara", "masa",

"james", "wade", "bosh", "hamslan", "bati"};

phones = new String[]{"15898930099", "13909456674", "13465353623",

"15984347533", "18694335633", "18945660044", "13844423094", "15899335395", "18754636894", "13986745568"};

pictures = new Bitmap[]{getPicture(R.drawable.image1), getPicture(R.drawable.image2),

getPicture(R.drawable.image3), getPicture(R.drawable.image4),

getPicture(R.drawable.image5), getPicture(R.drawable.image6),

getPicture(R.drawable.image7), getPicture(R.drawable.image8),

getPicture(R.drawable.image9), getPicture(R.drawable.image10)};



for (int i = 0; i < names.length; i++)

{

mPictures.put(names[i], pictures[i]);

mPersons.put(names[i] , new Person(names[i], phones[i], mPictures));

}



}



//将Drawable转为Bitmap

private Bitmap getPicture(int resourceId)

{

BitmapDrawable bd = (BitmapDrawable)getResources().getDrawable(resourceId);



return bd.getBitmap();



}



@Override

public void onCreate()

{

// TODO Auto-generated method stub

super.onCreate();

init();

//person = new Person();

//创建ServiceBinder对象(Binder类型对象)

mServiceBinder = new ServiceBinder();

}



/*定义一个继承IMyService接口内部类Stub的实现与客户端通信的Binder类型的类,

* IMyService.Stub是Binder类型

*/

public class ServiceBinder extends IMyService.Stub

{



@Override

public Person getPerson(String name) throws RemoteException

{

// TODO Auto-generated method stub

//根据传进来的用户姓名,返回对应的Person对象

return mPersons.get(name);

}

}



@Override

public IBinder onBind(Intent arg0)

{

// TODO Auto-generated method stub



/*与客户端连接时,返回该Binder对象.

* 1.如果连接的客户端和该服务端属于同一个进程,则此处直接返回mServiceBinder本身

* 2.如果连接的客户端和该服务不属于同一个进程,则返回的是mServiceBinder对象的代理

*/

return mServiceBinder;

}

}

客户端的代码实现如下:

IpcClient.java

[java] view
plaincopy

package com.feixun.hu.ipc.client;



import java.util.ArrayList;

import java.util.List;



import android.app.Activity;

import android.app.Service;

import android.content.ComponentName;

import android.content.Context;

import android.content.Intent;

import android.content.ServiceConnection;

import android.os.Bundle;

import android.os.IBinder;

import android.os.RemoteException;

import android.view.LayoutInflater;

import android.view.View;

import android.view.View.OnClickListener;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.Button;

import android.widget.EditText;

import android.widget.ImageView;

import android.widget.ListView;

import android.widget.TextView;

import android.widget.Toast;



import com.feixun.hu.ipc.service.IMyService;

import com.feixun.hu.ipc.service.Person;



public class IpcClient extends Activity

{



private IMyService mIMyService;

private ContactAdapter mContactAdapter;

private Person mPerson;

private Button mGetInfo;

private ListView showView;

private EditText mInputName;

private List<Person> mPersons;



/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);



//获取各组件

mGetInfo = (Button) findViewById(R.id.get);

mInputName = (EditText) findViewById(R.id.person);

showView = (ListView)findViewById(R.id.show);



//创建mPersons集合对象

mPersons = new ArrayList<Person>();



//创建Intent,对应服务端注册的Intent

Intent intent = new Intent();

intent.setAction("com.feixun.hu.action.IPC_SERVICE");

//绑定连接远程服务

bindService(intent, conn, Service.BIND_AUTO_CREATE);



//为设置按钮绑定监听

mGetInfo.setOnClickListener(new OnClickListener()

{

@Override

public void onClick(View v)

{

// TODO Auto-generated method stub

if(mInputName.getText() != null )

{

try

{

String personName = mInputName.getText().toString();



//得到来自远程的Person对象mPerson

mPerson = mIMyService.getPerson(personName);



if (mPerson != null)

{

getInfo(mPerson);

}

}

catch (RemoteException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

});



}



//该方法实现在ListView显示从远程得到的相关信息

private void getInfo(Person person)

{

//将从远程得到的mPerson对象添加入mPersons集合

mPersons.add(person);



//通过远程得到的mPerson对象

mContactAdapter = new ContactAdapter(this, mPersons);

showView.setAdapter(mContactAdapter);

}



//实现客户端与服务端绑定的关键部分

private ServiceConnection conn = new ServiceConnection()

{

//解除连接服务端

@Override

public void onServiceDisconnected(ComponentName name)

{

// TODO Auto-generated method stub

mIMyService = null;

}

//连接服务端

@Override

public void onServiceConnected(ComponentName name, IBinder service)

{

// TODO Auto-generated method stub

/*此处实现获取通过IpcService的onBind方法返回的mServiceBinder对象的代理。

* 参数service为绑定获得的远程服务IpcService的mServiceBinder对象,

* 而调用IMyService.Stub的函数asInterface获取的是mServiceBinder对象的代理。

*/

mIMyService = IMyService.Stub.asInterface(service);

}

};



@Override

protected void onDestroy()

{

// TODO Auto-generated method stub

super.onDestroy();

//解除绑定

unbindService(conn);

}



//自定义适配器,然后将从远程得到的用户信息在ListView中显示

class ContactAdapter extends BaseAdapter

{



private List<Person> persons = null;

private LayoutInflater inflater = null;



public ContactAdapter(Context context, List<Person> person)

{

inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

persons = person;

//Log.d("MainActivity", "FxAdapter()");

}



@Override

public int getCount() {

// TODO Auto-generated method stub

return persons.size();

}



@Override

public Object getItem(int position) {

// TODO Auto-generated method stub

return persons.get(position);

}



@Override

public long getItemId(int position) {

// TODO Auto-generated method stub

return 0;

}



@Override

public View getView(int position, View convertView, ViewGroup parent)

{

// TODO Auto-generated method stub

//得到来自远程服务端的Person对象

Person person = (Person)persons.get(position);



ImageView mPictureView = null;

TextView mNameView = null;

TextView mPhoneView = null;



if (convertView == null)

{

convertView = inflater.inflate(R.layout.contact_list, null);

}



mPictureView = (ImageView)convertView.findViewById(R.id.user_image);

//显示头像

mPictureView.setImageBitmap(person.getPictures().get(person.getName()));

mNameView = (TextView)convertView.findViewById(R.id.name_id);

//显示姓名

mNameView.setText(person.getName());

mPhoneView = (TextView)convertView.findViewById(R.id.phone_id);

//显示手机号

mPhoneView.setText(person.getPhone());

return convertView;

}



}

}

关于通过实现Parcelable接口来进行程跨进程传递复杂数据的实现就到此结束了,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: