多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
#### 2.4.2 使用文件共享 **共享文件也是一种不错的进程间通信方式,两个进程通过读/写同一个文件来交换数据,比如A进程把数据写入文件,B进程通过读取这个文件来获取数据**。 我们知道,在Windows上,一个文件如果被加了排斥锁将会导致其他线程无法对其进行访问,包括读和写,而**由于Android系统基于Linux,使得其并发读/写文件可以没有限制地进行,甚至两个线程同时对同一个文件进行写操作都是允许的,尽管这可能出问题。通过文件交换数据很好使用,除了可以交换一些文本信息外,我们还可以序列化一个对象到文件系统中的同时从另一个进程中恢复这个对象**,下面就展示这种使用方法。 还是本章刚开始的那个例子(**在一个进程中修改sUserId的值只会影响当前进程,对其他进程不会造成任何影响**),这次我们在MainActivity的onResume中序列化一个User对象到sd卡上的一个文件里,然后在SecondActivity的onResume中去反序列化,我们期望在SecondActivity中能够正确地恢复User对象的值。关键代码如下: ``` //在MainActivity中的修改 private void persistToFile() { new Thread(new Runnable() { @Override public void run() { User user = new User(1, "hello world", false); File dir = new File(MyConstants.CHAPTER_2_PATH); if (!dir.exists()) { dir.mkdirs(); } File cachedFile = new File(MyConstants.CACHE_FILE_PATH); ObjectOutputStream objectOutputStream = null; try { objectOutputStream = new ObjectOutputStream( new FileOutputStream(cachedFile)); objectOutputStream.writeObject(user); Log.d(TAG, "persist user:" + user); } catch (IOException e) { e.printStackTrace(); } finally { MyUtils.close(objectOutputStream); } } }).start(); } //SecondActivity中的修改 private void recoverFromFile() { new Thread(new Runnable() { @Override public void run() { User user = null; File cachedFile = new File(MyConstants.CACHE_FILE_PATH); if (cachedFile.exists()) { ObjectInputStream objectInputStream = null; try { objectInputStream = new ObjectInputStream( new FileInputStream(cachedFile)); user = (User) objectInputStream.readObject(); Log.d(TAG, "recover user:" + user); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { MyUtils.close(objectInputStream); } } } }).start(); } ``` 下面看一下log,很显然,在SecondActivity中成功地从文件从恢复了之前存储的User对象的内容,这里之所以说内容,是因为**反序列化得到的对象只是在内容上和序列化之前的对象是一样的,但它们本质上还是两个对象**。 ``` D/MainActivity(10744): persist user:User:{userId:1, userName:hello world, isMale:false}, with child:{null} D/SecondActivity(10877): recover user:User:{userId:1, userName:hello world, isMale:false}, with child:{null} ``` **通过文件共享这种方式来共享数据对文件格式是没有具体要求的,比如可以是文本文件,也可以是XML文件,只要读/写双方约定数据格式即可**。 **通过文件共享的方式也是有局限性的,比如并发读/写的问题**,像上面的那个例子,**如果并发读/写,那么我们读出的内容就有可能不是最新的,如果是并发写的话那就更严重了。因此我们要尽量避免并发写这种情况的发生或者考虑使用线程同步来限制多个线程的写操作**。通过上面的分析,我们可以知道,**文件共享方式适合在对数据同步要求不高的进程之间进行通信,并且要妥善处理并发读/写的问题**。 当然,**SharedPreferences是个特例**,众所周知,**SharedPreferences是Android中提供的轻量级存储方案,它通过键值对的方式来存储数据,在底层实现上它采用XML文件来存储键值对,每个应用的SharedPreferences文件都可以在当前包所在的data目录下查看到**。一般来说,它的目录位于/data/data/package name/shared_prefs目录下,其中package name表示的是当前应用的包名。 **从本质上来说,SharedPreferences也属于文件的一种,但是由于系统对它的读/写有一定的缓存策略,即在内存中会有一份SharedPreferences文件的缓存,因此在多进程模式下,系统对它的读/写就变得不可靠,当面对高并发的读/写访问,Sharedpreferences有很大几率会丢失数据**,因此,**不建议在进程间通信中使用SharedPreferences**。