多进程的一些注意事项

1.如何开启:

给四大组件(Activity、Service、Receiver、ContentProvider)在AndroidManifest.xml中指定"android:process"属性可以在应用内实现多进程。

如果进程名以":"开头,说明该进程属于私有进程,其他应用的组件不可以和它跑在同一个进程中;

如果进程名不以":"开头,则属于全局进程,其它应用通过ShareUID方式可以和它跑在同一个进程中。

 

2.注意两个进程之间的数据:

Android为每个应用分配了一个独立的虚拟机,或者可以说每个进程都有一个独立的虚拟机,不同的虚拟机在内存分配上有不同的内存地址,这就导致不同的虚拟机访问同一个类的对象会产生多份副本。

所以,所有运行在不同进程中的四大组件,只要他们之间通过内存来共享数据,都会共享失败。

一般来说,使用多进程会有以下影响:

<1>.静态成员和单例模式完全失效

<2>.线程同步机制完全失效(因为都不是一块内存了,所以不同进程锁都不是同一个对象)

<3>.SharePreferences的可靠性下降(因为SharePreferences不支持两个进程同时进行写操作,会导致一定几率的数据丢失,这是因为SharePreferences底层是通过读写xml来实现的)

<4>.Application会多次创建

 

3.进程间通信

进程获取的内存空间是一块抽象的内存,然后会映射到实际的某一块物理内存,因此,每个进程都无法访问其他进程在内存里面数据。

不同进程之间的通信,就意味着在两块不同的物理内存间传递数据

当然,原生的数据,比如int或者String数据都是可以传递的,但是对象数据是不可以的

在Android中,最有特色的进程间通信方式就是Binder了,还可以支持Socket(既可以在两个设备之间Socket通信,也可以在一个设备的不同进程间通信)。

 

 4.Android IPC机制:
 
  (1).使用Bundle:一个进程启动另一个进程中的Activity,Service,BroadCastReceiver,那么可以在Bunlde中添加信息,并通过Intent传递
注意:传输的数据必须能够序列化,比如基本类型,实现了Serializable或者Parcelable接口的对象,一些Android支持的特殊对象
 
  (2).文件共享:进程A把数据写入文件,进程B去读取文件内容
注意:<1>.适合于数据同步要求不高的情况,要注意处理好并发读写的问题
   <2>.进程A写入一个对象,进程B读取出来一个对象,虽然两个对象的内容一致,但是注意两个对象本质上其实并不相同(因为使用了Serializable序列化对象,以及反射,反射导致了两个对象其实并不相同)
   <3>.虽然SharePreferences也是文件的一种,底层采用xml文件,目录位于/data/data/package name/shared_prefs目录下,但是由于系统对它的读写有一定的缓存策略,即在内存中会有一份SharePreferences文件的缓存,因为在多进程下,系统对它的读写很不靠谱。(虽然在API Level>=11即Android 3.0可以通过Context.MODE_MULTI_PROCESS属性来实现SharedPreferences多进程共享)
1 SharedPreferences myPrefs = context.getSharedPreferences(MY_FILE_NAME, Context.MODE_MULTI_PROCESS | Context.MODE_PRIVATE);

         一旦我们设置了这个Flag,每次调用Context.getSharedPreferences 的时候系统会重新从SP文件中读入数据,因此我们在使用的时候每次读取和存入都要使用Context.getSharedPreferences 重新获取SP实例。即使是这样,由于SP本质上并不是多进程安全的,所以还是无法保证数据的同步,因此该方法我们并没有使用,我们也不推荐使用。

    由于SP不是多进程安全的,可以使用一个多进程安全的开源项目:Tray  (但是需要的minsdk是15)

 1 // create a preference accessor. This is for global app preferences. 
 2 final AppPreferences appPreferences = new AppPreferences(getContext()); // this Preference comes for free from the library
 3 // save a key value pair 
 4 appPreferences.put("key", "lorem ipsum");
 5  
 6 // read the value for your key. the second parameter is a fallback (optional otherwise throws) 
 7 final String value = appPreferences.getString("key", "default");
 8 Log.v(TAG, "value: " + value); // value: lorem ipsum
 9  
10 // read a key that isn't saved. returns the default (or throws without default) 
11 final String defaultValue = appPreferences.getString("key2", "default");
12 Log.v(TAG, "value: " + defaultValue); // value: default



  (3).ContentProvider是Android官方支持的多进程安全的,参考:Android应用程序组件Content Provider应用实例

 
  (4).Messager:通过它可以在不同进程间传递Message对象,在Message中放入要传递的数据
 
 
   (5).AIDL

注意<1>Messager只能串行处理消息,如果要处理大量的消息的话,还是用aidl

      <2>:在AIDL文件中,并不是所有的数据类型都是可以使用的,AIDL只支持以下数据类型

       (1).基本数据类型(intlongcharbooleandouble)

       (2).StringCharSequence

       (3).List:只支持ArrayList,里面的每个元素都必须能够被AIDL支持

       (4).Map:只支持HashMap,里面的每个元素都必须能够被AIDL支持,包括keyvalue

       (5).Parcelable:所有实现了Parcelable接口的对象

       (6).AIDL:所有的AIDL接口本身也可以在AIDL文件中使用

posted @ 2016-03-22 00:20  TwoFish  阅读(1661)  评论(0编辑  收藏  举报