Android IPC 文件共享

共享文件也是一种不错的IPC方式,两个进程通过读写同一个文件来交换数据,比如A进程把数据写入文件,B进程通过读取文件来获取数据。由于Android基于Linux,所以并发读写没有什么限制,甚至线程同时读写文件都可以,尽管会出现问题。利用这个思想,我们可以序列化一个对象到文件系统中,同时另一个进程中回复这个对象。

还是以上一个工程为例:

在MainActivity添加以下代码:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. protected void onResume() {  
  3.     persistToFile();  
  4.     super.onStart();  
  5. }  
  6.   
  7. private void persistToFile() {  
  8.     new Thread(new Runnable() {  
  9.   
  10.         @Override  
  11.         public void run() {  
  12.             String path = Environment.getExternalStorageDirectory().getPath()  
  13.              + "/qian/";  
  14.             User user = new User(1"hello world"false);  
  15.             File dir = new File(path);  
  16.             if (!dir.exists()) {  
  17.                 dir.mkdirs();  
  18.             }  
  19.             File cachedFile = new File(path + "cache");  
  20.             ObjectOutputStream objectOutputStream = null;  
  21.             try {  
  22.                 objectOutputStream = new ObjectOutputStream(  
  23.                         new FileOutputStream(cachedFile));  
  24.                 objectOutputStream.writeObject(user);  
  25.                 Log.i(TAG, "persist user:" + user);  
  26.             } catch (IOException e) {  
  27.                 e.printStackTrace();  
  28.             } finally {  
  29.                   
  30.                   
  31.                 try {  
  32.                     if(objectOutputStream != null)  
  33.         objectOutputStream.close();  
  34.     } catch (IOException e) {  
  35.         e.printStackTrace();  
  36.     }  
  37.                 
  38.   
  39.             }  
  40.         }  
  41.     }).start();  
  42. }  

在BundleActivty添加如下代码:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2.  protected void onResume() {  
  3.      super.onResume();  
  4.     // User user = (User) getIntent().getSerializableExtra("extra_user");  
  5.      Log.d(TAG, "onResume");  
  6.      recoverFromFile();  
  7.  }  
  8.   
  9.  private void recoverFromFile() {  
  10.      new Thread(new Runnable() {  
  11.   
  12.          @Override  
  13.          public void run() {  
  14.              User user = null;  
  15.              String path = Environment.getExternalStorageDirectory().getPath()  
  16.                      + "/qian/";  
  17.              File cachedFile = new File(path + "cache");  
  18.              if (cachedFile.exists()) {  
  19.                  ObjectInputStream objectInputStream = null;  
  20.                  try {  
  21.                      objectInputStream = new ObjectInputStream(  
  22.                              new FileInputStream(cachedFile));  
  23.                      user = (User) objectInputStream.readObject();  
  24.                      Log.i(TAG, "recover user:" + user);  
  25.                  } catch (IOException e) {  
  26.                      e.printStackTrace();  
  27.                  } catch (ClassNotFoundException e) {  
  28.                      e.printStackTrace();  
  29.                  } finally {  
  30.                     try {  
  31.                         if(objectInputStream != null)  
  32.                         objectInputStream.close();  
  33.                     } catch (IOException e) {  
  34.                         e.printStackTrace();  
  35.                     }  
  36.                  }  
  37.              }  
  38.          }  
  39.      }).start();  
  40.  }  

其实一个序列化与反序列化的过程,其中定义了一个可序列化的对象User,继承自Parcelable, Serializable接口,这样便可以序列化,User代码如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.qian.ipc;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5.   
  6.   
  7. import android.os.Parcel;  
  8. import android.os.Parcelable;  
  9.   
  10. public class User implements Parcelable, Serializable {  
  11.     private static final long serialVersionUID = 519067123721295773L;  
  12.   
  13.     public int userId;  
  14.     public String userName;  
  15.     public boolean isMale;  
  16.   
  17.     public Book book;  
  18.   
  19.     public User() {  
  20.     }  
  21.   
  22.     public User(int userId, String userName, boolean isMale) {  
  23.         this.userId = userId;  
  24.         this.userName = userName;  
  25.         this.isMale = isMale;  
  26.     }  
  27.   
  28.     public int describeContents() {  
  29.         return 0;  
  30.     }  
  31.   
  32.     public void writeToParcel(Parcel out, int flags) {  
  33.         out.writeInt(userId);  
  34.         out.writeString(userName);  
  35.         out.writeInt(isMale ? 1 : 0);  
  36.         out.writeParcelable(book, 0);  
  37.     }  
  38.   
  39.     public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {  
  40.         public User createFromParcel(Parcel in) {  
  41.             return new User(in);  
  42.         }  
  43.   
  44.         public User[] newArray(int size) {  
  45.             return new User[size];  
  46.         }  
  47.     };  
  48.   
  49.     private User(Parcel in) {  
  50.         userId = in.readInt();  
  51.         userName = in.readString();  
  52.         isMale = in.readInt() == 1;  
  53.         book = in  
  54.                 .readParcelable(Thread.currentThread().getContextClassLoader());  
  55.     }  
  56.   
  57.     @Override  
  58.     public String toString() {  
  59.         return String.format(  
  60.                 "User:{userId:%s, userName:%s, isMale:%s}, with child:{%s}",  
  61.                 userId, userName, isMale, book);  
  62.     }  
  63.   
  64. }  

最终打印的Log如下:只要红色框圈住的,其中红色框中第二栏Application打印的是进程名,可以看出MainActivity和BundleActivity是属于不同进程的。很显然,BundleActivity成功的从文件中回复了之前存储的User对象的内容,这里之所以说内容,是因为反序列化得到的对象只是在内容上和序列化之前的对象式样的,但他们本质上是两个对象。



通过文件共享这种方式来共享数据对文件格式是没有具体要求的,比如可以是文本文件,也可以是xml文件,只要读写双方约定数据格式即可,也不一定要用序列化对象这种方式来实现文件共享,但是问题是要处理并发读写的问题。

另外SharePreferences是个特例,它是Android中提供的轻量级存储方案,通过键值对的方式存储数据,在底层实现上采用xml文件来存储键值对。但是SharePreferences也有一个问题,但是由于系统对SharePreferences的读写有一定的缓存策略,也就是说在内存中会有一份SharePreferences文件的缓存,因此在多进程模式下,系统对它的读写就变得不可靠,当面对高并发的读写访问SharePreferences有很大几率会丢失数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序邦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值