一個枚舉搞定Activity之間的數據傳遞

正常我們從一個activity跳入另一個界面時候,如果需要攜帶參數。則代碼如下

 public static void startActivity(Activity activity,UserChange userChange){
        Intent intent = new Intent(activity,UserChangeActivity.class);
        intent.putExtra(DATA_KEY,userChange);
        activity.startActivity(intent);

    }

然後跳轉的activity裏面獲取數據

UserChange userChange;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
	userChange = (UserChange) getIntent().getSerializableExtra(DATA_KEY);
}

記得以前看ARouter源碼的時候。要跳轉的activity只要在字段上面加個註解。就能自動解析傳遞過來的參數。想着實現起來也不難,於是手動擼起來。

跳轉的方法封裝先,我們定義了一個通用的key。封裝了跳轉時要帶參數的方法。這樣跳轉就很簡單了,只要把要跳轉的class和數據傳進去就可以了。

	public final static String INTENT_DATA_KEY="INTENT_DATA_KEY";
	/**
     * 跳轉到Activity
     *
     * @param clazz Activity類
     */
    protected void startActivity(Class clazz,Object data) {
        Bundle bundle = new Bundle();
        putData(bundle,INTENT_DATA_KEY,data);
        startActivityForResult(clazz, -1, bundle);

    }

	private void putData(Bundle bundle,String key,Object data){
        if (data instanceof Integer){
            bundle.putInt(key,(Integer) data);
        }else if (data instanceof String){
            bundle.putString(key,(String) data);
        }else if(data instanceof Serializable){
            bundle.putSerializable(key,(Serializable) data);
        }
	}

接收的地方更簡單了,只要在屬性上面添加一個枚舉修飾

@IntentData
UserChange userChange;

當然如果多個參數,則屬性的枚舉對應的key要和這裏的map裏面的key一一對應

/**
 * 跳轉到Activity
 *
 * @param clazz Activity類
 */
protected void startActivity(Class clazz,Map<String,Object> datas) {
    Bundle bundle = new Bundle();
    for (Map.Entry<String, Object> entry : datas.entrySet()) {
        putData(bundle,entry.getKey(),entry.getValue());
    }
    startActivityForResult(clazz, -1, bundle);

}

枚舉,很簡單.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface IntentData {
    String key() default INTENT_DATA_KEY;

}

然後就是在onCreate裏面找到枚舉的字段,解析,賦值

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    resolveIntentData();
  
}

遍歷屬性,找到帶IntentData枚舉的屬性

void resolveIntentData(){

 Field[] fields= getClass().getDeclaredFields();
 for (int i=0;i<fields.length;i++){
     Field f = fields[i];
	
     IntentData intentData=f.getAnnotation(IntentData.class);
	//如果屬性上面有IntentData修飾
     if (intentData!=null) {
         setIntentData(intentData,f);
     }

 }
}

一個一個找到後賦值。這裏有個陷阱。Serializable判斷一定要放在最後,因爲其他的類型都實現了Serializeable接口,如果判斷放在最前面,則總是會符合條件。

private void setIntentData(IntentData intentData,Field f){
    if (intentData!=null){
        Intent intent = getIntent();
        //獲取註解字段的類型
        Class clazz=f.getType();
        Object o = null;
        String key = intentData.key();
		//根據字段的類型獲取
        if (Integer.class==clazz||int.class==clazz){
            o = intent.getIntExtra(key,0);
        }else if (String.class==clazz){
            o = intent.getStringExtra(key);
        } else if (Boolean.class==clazz||boolean.class==clazz){
            o = intent.getBooleanExtra(key,false);
        }else if (Serializable.class.isAssignableFrom(clazz)){
            o = intent.getSerializableExtra(key);
        }
		//如果獲取到,賦值
        if (o!=null) {
            ReflectUtil.setField(this, f.getName(), o);
        }
    }
}

賦值的操作就比較簡單。當然也可以像ButterKnife那樣。在編譯期自動生成代碼處理。只不過那樣難度大些。

public static Field getField(Class<?> clazz, String fieldName) {
    Field field = null;

    try {
        field = clazz.getDeclaredField(fieldName);
        field.setAccessible(true);
    } catch (NoSuchFieldException var4) {
        var4.printStackTrace();
    }

    return field;
}

public static void setField(Object obj, String fieldName, Object value) {
    Field field = getField(obj.getClass(), fieldName);
    if (field != null) {
        try {
            field.set(obj, value);
        } catch (IllegalAccessException var5) {
            var5.printStackTrace();
        }
    }

}

把上述代碼封裝在BaseActivity裏面,則後面跳轉界面傳遞參數就直接調用下面封裝方法。

	/**
     * 跳轉到Activity
     *
     * @param clazz Activity類
     */
    protected void startActivity(Class clazz,Object data) {
        Bundle bundle = new Bundle();
        putData(bundle,INTENT_DATA_KEY,data);
        startActivityForResult(clazz, -1, bundle);

    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章