Skip to content

Commit

Permalink
(自认为)优雅的支持跨进程的单例实现机制(toolbox + sample)
Browse files Browse the repository at this point in the history
  • Loading branch information
SR1s committed Mar 19, 2016
1 parent a1a0f64 commit de59913
Show file tree
Hide file tree
Showing 26 changed files with 903 additions and 5 deletions.
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ dependencies {
compile 'com.android.support:recyclerview-v7:22.1.1' compile 'com.android.support:recyclerview-v7:22.1.1'
compile 'com.facebook.fresco:fresco:0.6.1' compile 'com.facebook.fresco:fresco:0.6.1'
compile 'com.tencent.bugly:crashreport:1.2.3.8' compile 'com.tencent.bugly:crashreport:1.2.3.8'
/** ButterKnife */
compile 'com.jakewharton:butterknife:7.0.1'
} }


/** Bugly Crash上报相关配置 */ /** Bugly Crash上报相关配置 */
Expand Down
24 changes: 19 additions & 5 deletions app/src/main/AndroidManifest.xml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name"> 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>
<activity android:name=".sample.SampleActivity" /> <activity android:name=".sample.SampleActivity" />
<activity android:name=".demos.DemosIndexActivity" /> <activity android:name=".demos.DemosIndexActivity" />
Expand Down Expand Up @@ -65,6 +60,25 @@
<action android:name="playground.android.me.sr1.androidplayground.demos.service.MAIN_PROCESS_SERVICE_WITH_INTENT_FILTER" /> <action android:name="playground.android.me.sr1.androidplayground.demos.service.MAIN_PROCESS_SERVICE_WITH_INTENT_FILTER" />
</intent-filter> </intent-filter>
</service> </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> </application>


</manifest> </manifest>
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,5 @@
package playground.android.me.sr1.androidplayground.sample.mutilprocess.processA;

interface SingletonA {
void invokeA(String aString);
}
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,5 @@
package playground.android.me.sr1.androidplayground.sample.mutilprocess.processB;

interface SingletonB {
void invokeB(String aString);
}
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,5 @@
package playground.android.me.sr1.androidplayground.sample.mutilprocess.processC;

interface SingletonC {
void invokeC(String aString);
}
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,3 @@
package playground.android.me.sr1.androidplayground.toolbox.component.mutilprocess.singleton;

parcelable InstanceCarrier;
Original file line number Original file line Diff line number Diff line change
@@ -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();
}
Original file line number Original file line Diff line number Diff line change
@@ -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);
}
}
}
Original file line number Original file line Diff line number Diff line change
@@ -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 {}
Original file line number Original file line Diff line number Diff line change
@@ -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()));
}
}
Original file line number Original file line Diff line number Diff line change
@@ -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);
}
}
}
Original file line number Original file line Diff line number Diff line change
@@ -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 {}
Loading

0 comments on commit de59913

Please sign in to comment.