package me.ele.amigo.stub;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.util.Log;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
public abstract class ActivityStub extends Activity {
private static final List<Class<? extends ActivityStub>> SINGLE_TOP_STUBS = Arrays.asList(
SingleTopStub1.class,
SingleTopStub2.class,
SingleTopStub3.class,
SingleTopStub4.class,
SingleTopStub5.class,
SingleTopStub6.class,
SingleTopStub7.class,
SingleTopStub8.class);
private static final List<Class<? extends ActivityStub>> SINGLE_TASK_STUBS = Arrays.asList(
SingleTaskStub1.class,
SingleTaskStub2.class,
SingleTaskStub3.class,
SingleTaskStub4.class,
SingleTaskStub5.class,
SingleTaskStub6.class,
SingleTaskStub7.class,
SingleTaskStub8.class);
private static final List<Class<? extends ActivityStub>> SINGLE_INSTANCE_STUBS = Arrays.asList(
SingleInstanceStub1.class,
SingleInstanceStub1.class,
SingleInstanceStub2.class,
SingleInstanceStub3.class,
SingleInstanceStub4.class,
SingleInstanceStub5.class,
SingleInstanceStub6.class,
SingleInstanceStub7.class,
SingleInstanceStub8.class);
// [stub activity name : target activity instance]
private static final Map<String, ActivityRecord> usedSingleTopStubs = new LinkedHashMap<>
(SINGLE_TOP_STUBS.size(), 0.75f, true);
private static final Map<String, ActivityRecord> usedSingleTaskStubs = new LinkedHashMap<>
(SINGLE_TASK_STUBS.size(), 0.75f, true);
private static final Map<String, ActivityRecord> usedSingleInstanceStubs = new
LinkedHashMap<>(SINGLE_INSTANCE_STUBS.size(), 0.75f, true);
private static Class findActivityStub(String componentName, Map<String, ActivityRecord>
recordMap, List<Class<? extends ActivityStub>> stubs) {
Log.d("stub", "findActivityStub for component[" + componentName + "]");
for (Class stub : stubs) {
ActivityRecord record = recordMap.get(stub.getName());
if (record != null && record.activityClazzName.equals(componentName)) {
Log.d("stub", "startStubActivity: (reopen) stubClazz = " + stub);
return stub;
}
}
for (Class stub : stubs) {
if (!recordMap.containsKey(stub.getName())) {
Log.d("stub", "startStubActivity: stubClazz = " + stub);
return stub;
}
}
return null;
}
private static void recycleEarliestUsedActivityStub(Map<String, ActivityRecord> recordMap,
int limit) {
if (recordMap.size() < limit) {
return;
}
Iterator<Map.Entry<String, ActivityRecord>> it = recordMap.entrySet().iterator();
while (it.hasNext()) {
ActivityRecord activityRecord = it.next().getValue();
if (activityRecord.activity != null && !activityRecord.activity.isFinishing()) {
activityRecord.activity.finish();
it.remove();
break;
}
}
}
private static Map<String, ActivityRecord> getActivityRecordMap(Class stubActivityClazz) {
String clazzName = stubActivityClazz.getName();
String subStr = clazzName.substring(0, clazzName.length() - 1);
Map<String, ActivityRecord> recordMap = null;
if (subStr.endsWith("SingleTopStub")) {
recordMap = usedSingleTopStubs;
} else if (subStr.endsWith("SingleTaskStub")) {
recordMap = usedSingleTaskStubs;
} else if (subStr.endsWith("SingleInstanceStub")) {
recordMap = usedSingleInstanceStubs;
}
return recordMap;
}
public static Class selectActivityStubClazz(ActivityInfo activityInfo) {
Class clazz;
switch (activityInfo.launchMode) {
case LAUNCH_SINGLE_TOP:
clazz = findActivityStub(activityInfo.name, usedSingleTopStubs, SINGLE_TOP_STUBS);
break;
case LAUNCH_SINGLE_TASK:
clazz = findActivityStub(activityInfo.name, usedSingleTaskStubs, SINGLE_TASK_STUBS);
break;
case LAUNCH_SINGLE_INSTANCE:
clazz = findActivityStub(activityInfo.name, usedSingleInstanceStubs,
SINGLE_INSTANCE_STUBS);
break;
default:
clazz = ActivityStub.StandardStub.class;
break;
}
return clazz;
}
public static void recycleActivityStub(ActivityInfo activityInfo) {
switch (activityInfo.launchMode) {
case LAUNCH_SINGLE_TOP:
recycleEarliestUsedActivityStub(usedSingleTopStubs, SINGLE_TOP_STUBS.size());
break;
case LAUNCH_SINGLE_TASK:
recycleEarliestUsedActivityStub(usedSingleTaskStubs, SINGLE_TASK_STUBS.size());
break;
case LAUNCH_SINGLE_INSTANCE:
recycleEarliestUsedActivityStub(usedSingleInstanceStubs, SINGLE_INSTANCE_STUBS
.size());
break;
default:
break;
}
}
public static void onActivityCreated(Class stubActivityClazz, Activity activity, String
activityClazzName /*alternatively*/) {
Map<String, ActivityRecord> recordMap = getActivityRecordMap(stubActivityClazz);
if (recordMap != null)
recordMap.put(stubActivityClazz.getName(), new ActivityRecord(activity,
activityClazzName));
}
public static void onActivityDestroyed(Class stubActivityClazz, Activity activity) {
Map<String, ActivityRecord> recordMap = getActivityRecordMap(stubActivityClazz);
if (recordMap == null) return;
Iterator<Map.Entry<String, ActivityRecord>> it = recordMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, ActivityRecord> entry = it.next();
if (entry.getValue().activity == activity) {
it.remove();
break;
}
}
}
// single instance activity stubs
public static class SingleInstanceStub1 extends ActivityStub {
}
public static class SingleInstanceStub2 extends ActivityStub {
}
public static class SingleInstanceStub3 extends ActivityStub {
}
public static class SingleInstanceStub4 extends ActivityStub {
}
public static class SingleInstanceStub5 extends ActivityStub {
}
public static class SingleInstanceStub6 extends ActivityStub {
}
public static class SingleInstanceStub7 extends ActivityStub {
}
public static class SingleInstanceStub8 extends ActivityStub {
}
// single task activity stubs
public static class SingleTaskStub1 extends ActivityStub {
}
public static class SingleTaskStub2 extends ActivityStub {
}
public static class SingleTaskStub3 extends ActivityStub {
}
public static class SingleTaskStub4 extends ActivityStub {
}
public static class SingleTaskStub5 extends ActivityStub {
}
public static class SingleTaskStub6 extends ActivityStub {
}
public static class SingleTaskStub7 extends ActivityStub {
}
public static class SingleTaskStub8 extends ActivityStub {
}
// single top activity stubs
public static class SingleTopStub1 extends ActivityStub {
}
public static class SingleTopStub2 extends ActivityStub {
}
public static class SingleTopStub3 extends ActivityStub {
}
public static class SingleTopStub4 extends ActivityStub {
}
public static class SingleTopStub5 extends ActivityStub {
}
public static class SingleTopStub6 extends ActivityStub {
}
public static class SingleTopStub7 extends ActivityStub {
}
public static class SingleTopStub8 extends ActivityStub {
}
public static class StandardStub extends ActivityStub {
}
private static class ActivityRecord {
public Activity activity;
public String activityClazzName;
public ActivityRecord(Activity activity, String activityClazzName) {
this.activity = activity;
this.activityClazzName = activity != null ? activity.getClass().getName() :
activityClazzName;
}
}
}