package com.tencent.util;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.renderscript.FieldPacker;
import android.view.View;
import android.webkit.WebView;
import android.widget.TextView;
/**
* 反射调用的类
*
*/
public class ReflectedMethods {
/**
* 多进程间共享同一个SharePrefrence时,使用该方法加载SharePrefrence。<br>
* 该方法当API LEVEL > 11时,使用MODE_MULTI_PROCESS模式加载SharePrefrence。否则,使用MODE_PRIVATE模式加载。
* @param context
* @param name
* @return
*/
public static SharedPreferences loadMultiProcessSharePrefrence(Context context, String name){
if(context == null || name == null || name.length() <= 0){
return null;
}
Class owennerClass;
int mode = -1;
try {
owennerClass = Class.forName("android.content.Context");
Field field = owennerClass.getField("MODE_MULTI_PROCESS");
mode = (Integer)field.get(owennerClass);
}
catch (ClassNotFoundException e1) {
// e1.printStackTrace();
}
catch (NoSuchFieldException e) {
// e.printStackTrace();
}
catch (IllegalArgumentException e) {
// e.printStackTrace();
}
catch (IllegalAccessException e) {
// e.printStackTrace();
}
catch(Exception e){
// e.printStackTrace();
}
if(mode == -1){
mode = Context.MODE_PRIVATE;
}
SharedPreferences preference = context.getSharedPreferences(name, mode);
return preference;
}
private final static ConcurrentHashMap<Class<?>, ConcurrentHashMap<String, Field>> REG_FIELD_CACHE;
private static ConcurrentHashMap<Class<?>, ArrayList<String>> PRELOAD_FIELD;
private final static ConcurrentHashMap<Class<?>, ConcurrentHashMap<String, Method>> REG_METHOD_CACHE;
private static ConcurrentHashMap<Class<?>, ArrayList<String>> PRELOAD_METHOD;
private final static ConcurrentHashMap<Class<?>, ConcurrentHashMap<String, Class<?>[]>> REG_METHOD_TYPES_CACHE;
private final static boolean IS_CACHE_REF;
private static int INIT_SIZE = 0;
static {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
REG_FIELD_CACHE = new ConcurrentHashMap<Class<?>, ConcurrentHashMap<String, Field>>(
6);
PRELOAD_FIELD = new ConcurrentHashMap<Class<?>, ArrayList<String>>(6);
REG_METHOD_CACHE = new ConcurrentHashMap<Class<?>, ConcurrentHashMap<String, Method>>(
6);
PRELOAD_METHOD = new ConcurrentHashMap<Class<?>, ArrayList<String>>(6);
REG_METHOD_TYPES_CACHE = new ConcurrentHashMap<Class<?>, ConcurrentHashMap<String, Class<?>[]>>(
4);
IS_CACHE_REF = true;
INIT_SIZE = 3;
regFieldCache(android.view.View.class, "mHasPerformedLongPress");
regFieldCache(android.view.View.class, "mPrivateFlags");
regFieldCache(android.view.View.class, "mAttachInfo");
INIT_SIZE = 2;
regFieldCache(TextView.class, "mSingleLine");
regFieldCache(TextView.class, "mTextSelectHandleRes");
INIT_SIZE = 3;
regMethodCache(WebView.class, "addJavascriptInterface", Object.class, String.class);
regMethodCache(WebView.class, "onPause");
regMethodCache(WebView.class, "onResume");
INIT_SIZE = 5;
regMethodCache(View.class,"dispatchFinishTemporaryDetach");
regMethodCache(View.class,"dispatchStartTemporaryDetach");
regMethodCache(View.class,"computeOpaqueFlags");
regMethodCache(View.class,"recomputePadding");
regMethodCache(View.class,"dispatchDetachedFromWindow");
} else {
REG_FIELD_CACHE = null;
REG_METHOD_CACHE = null;
REG_METHOD_TYPES_CACHE = null;
IS_CACHE_REF = false;
}
}
public final static <T> void regFieldCache(Class<T> ower, String name) {
if (IS_CACHE_REF) {
ConcurrentHashMap<String, Field> cache = REG_FIELD_CACHE.get(ower);
if (cache == null) {
cache = new ConcurrentHashMap<String, Field>(INIT_SIZE);
ArrayList<String> list = new ArrayList<String>(INIT_SIZE);
list.add(name);
PRELOAD_FIELD.put(ower, list);
REG_FIELD_CACHE.put(ower, cache);
} else {
PRELOAD_FIELD.get(ower).add(name);
}
}
}
public final static <T> void regMethodCache(Class<T> ower, String name,
Class<?>... parameterTypes) {
if (IS_CACHE_REF) {
ConcurrentHashMap<String, Method> cache = REG_METHOD_CACHE
.get(ower);
if (cache == null) {
cache = new ConcurrentHashMap<String, Method>(INIT_SIZE);
ArrayList<String> list = new ArrayList<String>(INIT_SIZE);
list.add(name);
PRELOAD_METHOD.put(ower, list);
REG_METHOD_CACHE.put(ower, cache);
} else {
PRELOAD_METHOD.get(ower).add(name);
}
if (parameterTypes != null) {
ConcurrentHashMap<String, Class<?>[]> pCache = REG_METHOD_TYPES_CACHE
.get(ower);
if (pCache == null) {
pCache = new ConcurrentHashMap<String, Class<?>[]>(1);
REG_METHOD_TYPES_CACHE.put(ower, pCache);
}
pCache.put(name, parameterTypes);
}
}
}
/**
* 2.3(3.0类似)GetField会把该类以及所有父类和所有的接口的Public Field 返回做缓存(软引用); 4.0 GetField
* 遍历自己和所有的父类,接口,以及父类的接口Public Field 直到找到 对应的Field
*
* @param ower
* @param name
* @return
* @throws NoSuchFieldException
*/
public final static <T> Field getField(Class<T> ower, String name)
throws NoSuchFieldException {
Field field = null;
if (IS_CACHE_REF) {
ConcurrentHashMap<String, Field> cache = REG_FIELD_CACHE.get(ower);
if (cache != null) {
field = cache.get(name);
if (field == null) {
// for (Map.Entry<String, Field> entry : cache.entrySet()) {
// if (entry.getValue() == null) {
// String key = entry.getKey();
// field = ower.getField(key);
// if (field != null)
// cache.put(key, field);
// }
// }
ArrayList<String> list = PRELOAD_FIELD.get(ower);
if(list != null && list.size() != 0){
for (String key : list) {
if(cache.get(key) == null){
field = ower.getField(key);
if (field != null)
cache.put(key, field);
}
}
list.clear();
PRELOAD_FIELD.remove(ower);
}else{
field = ower.getField(name);
if (field != null)
cache.put(name, field);
}
field = cache.get(name);
}
} else {
field = ower.getField(name);
cache = new ConcurrentHashMap<String, Field>(3);
cache.put(name, field);
REG_FIELD_CACHE.put(ower, cache);
}
} else {
field = ower.getField(name);
}
return field;
}
/**
* 2.3(3.0类似)getDeclaredField 会把该类 所有的Field 初始化返回缓存(软引用) 4.0
* getDeclaredField先在自己的静态字段中查找,然后实例字段中查找 (找到返回)
*
* @param ower
* @param name
* @return
* @throws NoSuchFieldException
*/
public final static <T> Field getDeclaredField(Class<T> ower, String name)
throws NoSuchFieldException {
Field field = null;
if (IS_CACHE_REF) {
ConcurrentHashMap<String, Field> cache = REG_FIELD_CACHE.get(ower);
if (cache != null) {
field = cache.get(name);
if (field == null) {
ArrayList<String> list = PRELOAD_FIELD.get(ower);
if(list != null && list.size() != 0){
for (String key : list) {
if(cache.get(key) == null){
field = ower.getDeclaredField(key);
if (field != null)
cache.put(key, field);
}
}
list.clear();
PRELOAD_FIELD.remove(ower);
}else{
field = ower.getDeclaredField(name);
if (field != null)
cache.put(name, field);
}
field = cache.get(name);
}
} else {
field = ower.getDeclaredField(name);
cache = new ConcurrentHashMap<String, Field>(2);
cache.put(name, field);
REG_FIELD_CACHE.put(ower, cache);
}
} else {
field = ower.getDeclaredField(name);
}
return field;
}
/**
* 2.3(3.0类似) getMethod 遍历自身以及所有父类以及接口的Public方法排序缓存 4.0 getMethod
* 从自己开始遍历,知道找到对应的Public方法(会判断是不是Public),然后同样递归到父类
*
* @param ower
* @param name
* @param parameterTypes
* @return
* @throws NoSuchMethodException
*/
public final static <T> Method getMethod(Class<T> ower, String name,
Class<?>... parameterTypes) throws NoSuchMethodException {
Method method = null;
if (IS_CACHE_REF) {
ConcurrentHashMap<String, Method> cache = REG_METHOD_CACHE
.get(ower);
if (cache != null) {
method = cache.get(name);
if (method == null) {
ArrayList<String> list = PRELOAD_METHOD.get(ower);
if(list != null && list.size() != 0){
for (String key : list) {
if(cache.get(key) == null){
Class<?>[] parameter = null;
ConcurrentHashMap<String, Class<?>[]> pCache = REG_METHOD_TYPES_CACHE
.get(ower);
if (pCache != null) {
parameter = pCache.get(key);
}
method = ower.getMethod(key, parameter);
if (method != null)
cache.put(key, method);
}
}
list.clear();
PRELOAD_METHOD.remove(ower);
}else{
method = ower.getMethod(name, parameterTypes);
if (method != null)
cache.put(name, method);
}
method = cache.get(name);
}
} else {
method = ower.getMethod(name, parameterTypes);
cache = new ConcurrentHashMap<String, Method>(4);
cache.put(name, method);
REG_METHOD_CACHE.put(ower, cache);
}
} else {
method = ower.getMethod(name, parameterTypes);
}
return method;
}
/**
* 2.3(3.0类似) getDeclaredMethod 返回该类所有的方法以及接口,排序缓存,然后查找对应的方法 4.0
* getDeclaredMethod 只会查找当前类的所有方法,先查找direct方法(static,private和<init>方法)
*
* @param ower
* @param name
* @param parameterTypes
* @return
* @throws NoSuchMethodException
*/
public final static <T> Method getDeclaredMethod(Class<T> ower,
String name, Class<?>... parameterTypes)
throws NoSuchMethodException {
Method method = null;
if (IS_CACHE_REF) {
ConcurrentHashMap<String, Method> cache = REG_METHOD_CACHE
.get(ower);
if (cache != null) {
method = cache.get(name);
if (method == null) {
ArrayList<String> list = PRELOAD_METHOD.get(ower);
if(list != null && list.size() != 0){
for (String key : list) {
if(cache.get(key) == null){
Class<?>[] parameter = null;
ConcurrentHashMap<String, Class<?>[]> pCache = REG_METHOD_TYPES_CACHE
.get(ower);
if (pCache != null) {
parameter = pCache.get(key);
}
method = ower.getDeclaredMethod(key, parameter);
if (method != null)
cache.put(key, method);
}
}
list.clear();
PRELOAD_METHOD.remove(ower);
}else{
method = ower.getDeclaredMethod(name, parameterTypes);
if (method != null)
cache.put(name, method);
}
method = cache.get(name);
}
} else {
method = ower.getDeclaredMethod(name, parameterTypes);
cache = new ConcurrentHashMap<String, Method>(4);
cache.put(name, method);
REG_METHOD_CACHE.put(ower, cache);
}
} else {
method = ower.getDeclaredMethod(name, parameterTypes);
}
return method;
}
private static Method GET_DECLARED_FIELDS = null;
private static boolean IS_ERR = false;
/**
* 返回该类的属性
* @param clazz
* @param publicOnly 是否只是Public
* @return
*/
public static Field[] getNativeDeclaredFields(Class<?> clazz, boolean publicOnly){
Field[] fields = null;
if(!IS_ERR){
try {
if(GET_DECLARED_FIELDS == null){
GET_DECLARED_FIELDS = Class.class.getDeclaredMethod("getDeclaredFields", Class.class,boolean.class);
GET_DECLARED_FIELDS.setAccessible(true);
}
fields = (Field[])GET_DECLARED_FIELDS.invoke(null, clazz, publicOnly);
} catch (Exception e) {
// TODO: handle exception
IS_ERR = true;
}catch (Error e) {
// TODO: handle exception
IS_ERR = true;
}
}
if(fields == null){//下面恶心的代码是不会走到的,但是为了安全保留一下
fields = clazz.getDeclaredFields();
if(publicOnly){
ArrayList<Field> fieldList = new ArrayList<Field>();
for (Field field : fields) {
if(Modifier.isPublic(field.getModifiers())){
fieldList.add(field);
}
}
fields = new Field[fieldList.size()];
fieldList.toArray(fields);
}
}
return fields;
}
}