Permalink
Browse files

(自认为)优雅的支持跨进程的单例实现机制(toolbox + sample)

  • Loading branch information...
SR1s committed Mar 19, 2016
1 parent a1a0f64 commit de59913790b94ea65806cae5fecc9ae581d0c87d
Showing with 903 additions and 5 deletions.
  1. +2 −0 app/build.gradle
  2. +19 −5 app/src/main/AndroidManifest.xml
  3. +5 −0 ...ain/aidl/playground/android/me/sr1/androidplayground/sample/mutilprocess/processA/SingletonA.aidl
  4. +5 −0 ...ain/aidl/playground/android/me/sr1/androidplayground/sample/mutilprocess/processB/SingletonB.aidl
  5. +5 −0 ...ain/aidl/playground/android/me/sr1/androidplayground/sample/mutilprocess/processC/SingletonC.aidl
  6. +3 −0 ...nd/android/me/sr1/androidplayground/toolbox/component/mutilprocess/singleton/InstanceCarrier.aidl
  7. +7 −0 ...d/android/me/sr1/androidplayground/toolbox/component/mutilprocess/singleton/InstanceTransfer.aidl
  8. +105 −0 ...main/java/playground/android/me/sr1/androidplayground/sample/mutilprocess/processA/ActivityA.java
  9. +8 −0 .../main/java/playground/android/me/sr1/androidplayground/sample/mutilprocess/processA/ServiceA.java
  10. +56 −0 .../java/playground/android/me/sr1/androidplayground/sample/mutilprocess/processA/SingletonAImp.java
  11. +105 −0 ...main/java/playground/android/me/sr1/androidplayground/sample/mutilprocess/processB/ActivityB.java
  12. +8 −0 .../main/java/playground/android/me/sr1/androidplayground/sample/mutilprocess/processB/ServiceB.java
  13. +55 −0 .../java/playground/android/me/sr1/androidplayground/sample/mutilprocess/processB/SingletonBImp.java
  14. +106 −0 ...main/java/playground/android/me/sr1/androidplayground/sample/mutilprocess/processC/ActivityC.java
  15. +8 −0 .../main/java/playground/android/me/sr1/androidplayground/sample/mutilprocess/processC/ServiceC.java
  16. +55 −0 .../java/playground/android/me/sr1/androidplayground/sample/mutilprocess/processC/SingletonCImp.java
  17. +16 −0 ...n/java/playground/android/me/sr1/androidplayground/sample/mutilprocess/utils/MainThreadUtils.java
  18. +28 −0 ...main/java/playground/android/me/sr1/androidplayground/sample/mutilprocess/utils/ProcessUtils.java
  19. +20 −0 ...ground/android/me/sr1/androidplayground/toolbox/component/mutilprocess/singleton/BaseService.java
  20. +138 −0 ...nd/android/me/sr1/androidplayground/toolbox/component/mutilprocess/singleton/InstanceCarrier.java
  21. +31 −0 ...d/android/me/sr1/androidplayground/toolbox/component/mutilprocess/singleton/InstanceReceiver.java
  22. +14 −0 ...ndroid/me/sr1/androidplayground/toolbox/component/mutilprocess/singleton/InstanceTransferImp.java
  23. +34 −0 app/src/main/java/playground/android/me/sr1/androidplayground/toolbox/utils/AppUtils.java
  24. +35 −0 app/src/main/res/layout/activity_ABC.xml
  25. +21 −0 app/src/main/res/layout/fragment_demos_ui_ripple.xml
  26. +14 −0 app/src/main/res/layout/item_ripple.xml
@@ -27,6 +27,8 @@ dependencies {
compile 'com.android.support:recyclerview-v7:22.1.1'
compile 'com.facebook.fresco:fresco:0.6.1'
compile 'com.tencent.bugly:crashreport:1.2.3.8'
/** ButterKnife */
compile 'com.jakewharton:butterknife:7.0.1'
}
/** Bugly Crash上报相关配置 */
@@ -20,11 +20,6 @@
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".sample.SampleActivity" />
<activity android:name=".demos.DemosIndexActivity" />
@@ -65,6 +60,25 @@
<action android:name="playground.android.me.sr1.androidplayground.demos.service.MAIN_PROCESS_SERVICE_WITH_INTENT_FILTER" />
</intent-filter>
</service>
<service android:name=".sample.mutilprocess.processA.ServiceA" />
<activity android:name=".sample.mutilprocess.processA.ActivityA" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".sample.mutilprocess.processA.ServiceA" />
<activity android:name=".sample.mutilprocess.processB.ActivityB"
android:process=":B" />
<service android:name=".sample.mutilprocess.processB.ServiceB"
android:process=":B" />
<activity android:name=".sample.mutilprocess.processC.ActivityC"
android:process=":C" />
<service android:name=".sample.mutilprocess.processC.ServiceC"
android:process=":C" />
</application>
</manifest>
@@ -0,0 +1,5 @@
package playground.android.me.sr1.androidplayground.sample.mutilprocess.processA;
interface SingletonA {
void invokeA(String aString);
}
@@ -0,0 +1,5 @@
package playground.android.me.sr1.androidplayground.sample.mutilprocess.processB;
interface SingletonB {
void invokeB(String aString);
}
@@ -0,0 +1,5 @@
package playground.android.me.sr1.androidplayground.sample.mutilprocess.processC;
interface SingletonC {
void invokeC(String aString);
}
@@ -0,0 +1,3 @@
package playground.android.me.sr1.androidplayground.toolbox.component.mutilprocess.singleton;
parcelable InstanceCarrier;
@@ -0,0 +1,7 @@
package playground.android.me.sr1.androidplayground.toolbox.component.mutilprocess.singleton;
import playground.android.me.sr1.androidplayground.toolbox.component.mutilprocess.singleton.InstanceCarrier;
interface InstanceTransfer {
InstanceCarrier transfer();
}
@@ -0,0 +1,105 @@
package playground.android.me.sr1.androidplayground.sample.mutilprocess.processA;
import android.content.Context;
import android.content.Intent;
import android.os.*;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import playground.android.me.sr1.androidplayground.App;
import playground.android.me.sr1.androidplayground.R;
import playground.android.me.sr1.androidplayground.sample.mutilprocess.processB.ActivityB;
import playground.android.me.sr1.androidplayground.sample.mutilprocess.processB.ServiceB;
import playground.android.me.sr1.androidplayground.sample.mutilprocess.processB.SingletonBImp;
import playground.android.me.sr1.androidplayground.sample.mutilprocess.processC.ServiceC;
import playground.android.me.sr1.androidplayground.sample.mutilprocess.processC.SingletonCImp;
import playground.android.me.sr1.androidplayground.toolbox.component.mutilprocess.singleton.InstanceReceiver;
import playground.android.me.sr1.androidplayground.toolbox.utils.AppUtils;
/**
* @author SR1s
*/
public class ActivityA extends AppCompatActivity {
private static String TAG = "ActivityA";
@Bind(R.id.textView1) TextView mTextView1;
@Bind(R.id.button0) Button mBtn0;
@Bind(R.id.button1) Button mBtn1;
@Bind(R.id.button2) Button mBtn2;
@Bind(R.id.button3) Button mBtn3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_abc);
ButterKnife.bind(this);
mTextView1.setText("这里是主进程A");
mBtn0.setText("启动进程B");
mBtn1.setText("调用本主进程A的方法)");
mBtn2.setText("调用其他进程B的方法");
mBtn3.setText("调用其他进程C的方法");
/** 把其他进程的单例绑定过来 */
bindService(ServiceB.class);
bindService(ServiceC.class);
}
void bindService(Class<?> clz) {
Intent intent = new Intent(this, clz);
bindService(intent, new InstanceReceiver(), Context.BIND_AUTO_CREATE);
}
@OnClick(R.id.button0)
void startActivty() {
Intent intent = new Intent(this, ActivityB.class);
startActivity(intent);
}
@OnClick(R.id.button1)
void invokeAInstance() {
try {
Log.i(TAG, String.format("[%s][invokeA][pid=%d][tid=%d]", AppUtils.currentProcessName(),
android.os.Process.myPid(), android.os.Process.myTid()));
SingletonAImp.getInstance().invokeA(AppUtils.currentProcessName());
Toast.makeText(App.getContext(), "调用A单例方法", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e(TAG, "[invokeA][fail]", e);
}
}
@OnClick(R.id.button2)
void invokeBInstance() {
try {
Log.i(TAG, String.format("[%s][invokeB][pid=%d][tid=%d]", AppUtils.currentProcessName(),
android.os.Process.myPid(), android.os.Process.myTid()));
SingletonBImp.getInstance().invokeB(AppUtils.currentProcessName());
Toast.makeText(App.getContext(), "调用B单例方法", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e(TAG, "[invokeB][fail]", e);
}
}
@OnClick(R.id.button3)
void invokeCInstance() {
try {
Log.i(TAG, String.format("[%s][invokeC][pid=%d][tid=%d]", AppUtils.currentProcessName(),
android.os.Process.myPid(), android.os.Process.myTid()));
SingletonCImp.getInstance().invokeC(AppUtils.currentProcessName());
Toast.makeText(App.getContext(), "调用单例C方法", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e(TAG, "[invoke][fail]", e);
}
}
}
@@ -0,0 +1,8 @@
package playground.android.me.sr1.androidplayground.sample.mutilprocess.processA;
import playground.android.me.sr1.androidplayground.toolbox.component.mutilprocess.singleton.BaseService;
/**
* @author SR1s
*/
public class ServiceA extends BaseService {}
@@ -0,0 +1,56 @@
package playground.android.me.sr1.androidplayground.sample.mutilprocess.processA;
import android.content.Context;
import android.content.Intent;
import android.os.*;
import android.os.Process;
import android.util.Log;
import android.widget.Toast;
import playground.android.me.sr1.androidplayground.App;
import playground.android.me.sr1.androidplayground.sample.mutilprocess.utils.MainThreadUtils;
import playground.android.me.sr1.androidplayground.sample.mutilprocess.utils.ProcessUtils;
import playground.android.me.sr1.androidplayground.toolbox.component.mutilprocess.singleton.InstanceReceiver;
import playground.android.me.sr1.androidplayground.toolbox.utils.AppUtils;
/**
* @author SR1s
*/
public class SingletonAImp extends SingletonA.Stub {
public static SingletonA INSTANCE;
public static synchronized SingletonA getInstance() {
if (ProcessUtils.isProcessA()) {
if (INSTANCE == null) {
INSTANCE = new SingletonAImp();
}
return INSTANCE;
} else {
if (INSTANCE == null) {
/** 自发重连 */
Intent intent = new Intent(App.getContext(), ServiceA.class);
App.getContext().bindService(intent, new InstanceReceiver(), Context.BIND_AUTO_CREATE);
}
return INSTANCE;
}
}
private SingletonAImp() {}
public static final String TAG = "SingletonAImp";
@Override
public void invokeA(final String aString) throws RemoteException {
MainThreadUtils.runOnMainThread(new Runnable() {
@Override
public void run() {
Toast.makeText(App.getContext(),
String.format("[SingletonA]\n[调用进程:%s]\n[执行进程:%s]\n", aString, AppUtils.currentProcessName()),
Toast.LENGTH_SHORT).show();
}
});
Log.i(TAG, String.format("[%s][invokeA][pid=%d][tid=%d]",
aString, android.os.Process.myPid(), Process.myTid()));
}
}
@@ -0,0 +1,105 @@
package playground.android.me.sr1.androidplayground.sample.mutilprocess.processB;
import android.content.Context;
import android.content.Intent;
import android.os.*;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import playground.android.me.sr1.androidplayground.App;
import playground.android.me.sr1.androidplayground.R;
import playground.android.me.sr1.androidplayground.sample.mutilprocess.processA.ServiceA;
import playground.android.me.sr1.androidplayground.sample.mutilprocess.processA.SingletonAImp;
import playground.android.me.sr1.androidplayground.sample.mutilprocess.processC.ActivityC;
import playground.android.me.sr1.androidplayground.sample.mutilprocess.processC.ServiceC;
import playground.android.me.sr1.androidplayground.sample.mutilprocess.processC.SingletonCImp;
import playground.android.me.sr1.androidplayground.toolbox.component.mutilprocess.singleton.InstanceReceiver;
import playground.android.me.sr1.androidplayground.toolbox.utils.AppUtils;
/**
* @author SR1s
*/
public class ActivityB extends AppCompatActivity {
private static String TAG = "ActivityB";
@Bind(R.id.textView1) TextView mTextView1;
@Bind(R.id.button0) Button mBtn0;
@Bind(R.id.button1) Button mBtn1;
@Bind(R.id.button2) Button mBtn2;
@Bind(R.id.button3) Button mBtn3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_abc);
ButterKnife.bind(this);
mTextView1.setText("这里是进程B");
mBtn0.setText("启动进程C");
mBtn1.setText("调用主进程A的方法)");
mBtn2.setText("调用本进程B的方法");
mBtn3.setText("调用其他进程C的方法");
/** 把其他进程的单例绑定过来 */
bindService(ServiceA.class);
bindService(ServiceC.class);
}
void bindService(Class<?> clz) {
Intent intent = new Intent(this, clz);
bindService(intent, new InstanceReceiver(), Context.BIND_AUTO_CREATE);
}
@OnClick(R.id.button0)
void startActivty() {
Intent intent = new Intent(this, ActivityC.class);
startActivity(intent);
}
@OnClick(R.id.button1)
void invokeAInstance() {
try {
Log.i(TAG, String.format("[%s][invokeA][pid=%d][tid=%d]", AppUtils.currentProcessName(),
android.os.Process.myPid(), android.os.Process.myTid()));
SingletonAImp.getInstance().invokeA(AppUtils.currentProcessName());
Toast.makeText(App.getContext(), "调用A单例方法", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e(TAG, "[invokeA][fail]", e);
}
}
@OnClick(R.id.button2)
void invokeBInstance() {
try {
Log.i(TAG, String.format("[%s][invokeB][pid=%d][tid=%d]", AppUtils.currentProcessName(),
android.os.Process.myPid(), android.os.Process.myTid()));
SingletonBImp.getInstance().invokeB(AppUtils.currentProcessName());
Toast.makeText(App.getContext(), "调用B单例方法", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e(TAG, "[invokeB][fail]", e);
}
}
@OnClick(R.id.button3)
void invokeCInstance() {
try {
Log.i(TAG, String.format("[%s][invokeC][pid=%d][tid=%d]", AppUtils.currentProcessName(),
android.os.Process.myPid(), android.os.Process.myTid()));
SingletonCImp.getInstance().invokeC(AppUtils.currentProcessName());
Toast.makeText(App.getContext(), "调用单例C方法", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e(TAG, "[invoke][fail]", e);
}
}
}
@@ -0,0 +1,8 @@
package playground.android.me.sr1.androidplayground.sample.mutilprocess.processB;
import playground.android.me.sr1.androidplayground.toolbox.component.mutilprocess.singleton.BaseService;
/**
* @author SR1s
*/
public class ServiceB extends BaseService {}
Oops, something went wrong.

0 comments on commit de59913

Please sign in to comment.