一、文件進行IPC介紹 共用文件也是一種不錯的進程間通信方式,兩個進程通過讀/寫同一個文件來交換數據。在Windows上,一個文件如果被加了排斥鎖將會導致其他線程無法對其進行訪問,包括讀寫,而由於Android系統基於Linux,使其併發讀/寫文件可以沒有限制地進行,甚至兩個線程同時對同一個文件進行 ...
一、文件進行IPC介紹
共用文件也是一種不錯的進程間通信方式,兩個進程通過讀/寫同一個文件來交換數據。在Windows上,一個文件如果被加了排斥鎖將會導致其他線程無法對其進行訪問,包括讀寫,而由於Android系統基於Linux,使其併發讀/寫文件可以沒有限制地進行,甚至兩個線程同時對同一個文件進行讀寫操作是允許的,儘管這可能出現問題。通過文件交換數據很好使用,除了可以交換一些文本信息外,還可以序列化一個對象到文件系統中的同時從另一個進程中恢復這個對象。
二、使用方法
1.數據類實現Parcelable或Serializable介面
public class User implements Parcelable, Serializable { public User() { } public User(int userId, String userName, boolean isMale) { ... } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { ... } public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() { @Override public User createFromParcel(Parcel source) { return ...; } @Override public User[] newArray(int size) { return ...; } }; private User(Parcel in) { ... } @Override public String toString() { return ...; } }
2.序列化一個對象到sd卡上的一個文件里
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); mTextView.setText("persist user:" + user); } catch (IOException e) { e.printStackTrace(); } finally { MyUtils.close(objectOutputStream); } } }).start(); }
3.在另外的進程中反序列化
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); mTextView.setText("recover user:"+user); }catch (IOException e) { e.printStackTrace(); }catch (ClassNotFoundException e){ e.printStackTrace(); }finally { MyUtils.close(objectInputStream); } } } }).start(); }
4.在AndroidManifest.xml中開啟多進程
<activity
...
android:process=":remote" />
三、小案例
1.修改activity_main.xml文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.zhangmiao.ipcdemo.MainActivity" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="File"> </TextView> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="open activity B" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="A"> </TextView> </LinearLayout>
2.添加activity_second.xml文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="at activity B" android:layout_gravity="center_horizontal" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Activity B" /> </LinearLayout>
3.添加MyUtils類與MyConstants類(輔助類)
package com.zhangmiao.ipcdemo; import android.app.ActivityManager; import android.content.Context; import java.io.Closeable; import java.io.IOException; import java.util.List; import java.util.concurrent.RecursiveTask; /** * Created by zhangmiao on 2016/12/26. */ public class MyUtils { public static void close(Closeable closeable) { try { if (closeable != null) { closeable.close(); } } catch (IOException e) { e.printStackTrace(); } } }
package com.zhangmiao.ipcdemo; import android.os.Environment; /** * Created by zhangmiao on 2016/12/26. */ public class MyConstants { public static final String CHAPTER_2_PATH = Environment.getExternalStorageDirectory().getPath() + "/zhangmiao/charpter_2/"; public static final String CACHE_FILE_PATH = CHAPTER_2_PATH + "usercache"; public static final int MSG_FROM_CLIENT = 0; public static final int MSG_FROM_SERVICE = 1; }
4.添加User類
package com.zhangmiao.ipcdemo; import android.os.Parcel; import android.os.Parcelable; import java.io.Serializable; /** * Created by zhangmiao on 2016/12/26. */ public class User implements Parcelable, Serializable { public static int sUserId = 1; private int userId; private String userName; private Boolean isMale; public User() { } public User(int userId, String userName, boolean isMale) { this.userId = userId; this.userName = userName; this.isMale = isMale; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(userId); dest.writeString(userName); dest.writeInt(isMale ? 1 : 0); } public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() { @Override public User createFromParcel(Parcel source) { return new User(source); } @Override public User[] newArray(int size) { return new User[size]; } }; private User(Parcel in) { userId = in.readInt(); userName = in.readString(); isMale = in.readInt() == 1; } @Override public String toString() { return String.format( "User:{userId:%s, userName:%s, isMale:%s},",userId, userName, isMale ); } }
5.添加SecondActivity類
package com.zhangmiao.ipcdemo; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.widget.TextView; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; /** * Created by zhangmiao on 2016/12/26. */ public class SecondActivity extends Activity { private static final String TAG = "SecondActivity"; private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); Log.d(TAG, "onCreate"); mTextView = (TextView)findViewById(R.id.textView1); } @Override protected void onResume() { Log.d(TAG,"onResume"); super.onResume(); User user = (User)getIntent().getSerializableExtra("extra_user"); Log.d(TAG,"user:"+user.toString()); recoverFromFile(); } 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); mTextView.setText("recover user:"+user); }catch (IOException e) { e.printStackTrace(); }catch (ClassNotFoundException e){ e.printStackTrace(); }finally { MyUtils.close(objectInputStream); } } } }).start(); } }
6.修改MainActivity類
package com.zhangmiao.ipcdemo; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); User.sUserId = 2; findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setClass(MainActivity.this, SecondActivity.class); User user = new User(0, "jake", true); intent.putExtra("extra_user", (Serializable) user); startActivity(intent); } }); mTextView = (TextView) findViewById(R.id.textView1); } @Override protected void onResume() { super.onResume(); Log.d(TAG, "UserManager.sUserId=" + User.sUserId); super.onStart(); persistToFile(); } 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); mTextView.setText("persist user:" + user); } catch (IOException e) { e.printStackTrace(); } finally { MyUtils.close(objectOutputStream); } } }).start(); } }
7.修改AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?> <manifest
xmlns:android="http://schemas.android.com/apk/res/android" package="com.zhangmiao.ipcdemo"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/app_name" android:launchMode="standard" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".SecondActivity" android:configChanges="screenLayout" android:label="@string/app_name" android:process=":remote" /> </application> </manifest>
完整代碼下載地址:https://github.com/ZhangMiao147/IPCDemo