架構師成長之路-基於android fragment通信的面向對象的萬能接口

前言
開發一個app時,常用Activity和Fragment,由於操作方便Fragment越來越受歡迎,這樣就避免不了Activity和Fragment、Fragment和Fragment之間的通信,我們知道Fragment和Fragment之間不能直接進行通信的,而是通過Activity進行通信。那麼Activity和Fragment有幾種通信方式呢,它們的優缺點又是什麼?
一 常用的Activity和Fragment幾種通信方式
1 通過Handle
在Activity創建一個Handle機制實例,然後在創建Fragment的通過構造方法把Handle實例傳遞過去,這樣Fragment就可以往Activity傳送數據了。但這樣如下缺點:
(1)Activity和Fragment之間耦合性增大;
(2)Activity處理後的結果不能實時反饋給Fragment;
(3)提高了內存泄漏風險;
2 使用static變量
缺點很明確增大內存消耗;
3 使用廣播
分別在Activity和Fragment中註冊廣播,這樣就可以實現通信了。其缺點:
(1)性能差,有延遲,用戶體驗就會差;
(2)一般使用的是標準廣播,一個發送,多個接收者,大材小用,性能差;
(3)代碼冗餘;
(4)傳播的數據有限;
4 EventBus 、rxBus(俗稱萬能油)
其使用方法參考官方文檔,其優點就是實用起來簡單方便,其缺點也很明顯:
(1)EventBus 、rxBus其內部使用的是反射機制,那麼其性能就會降低;
(2)代碼維護困難(不熟悉的項目代碼的新人很難找到實現的方法在是如何調用的);
(3)數據返回困難,它們是單向傳遞;
5 普通接口
在Fragment寫一個接口,讓Activity去實現這個接口,通過這個接口把Activity與Fragment綁定在一起,這樣Activity和Fragment實時進行通信了,其實谷歌推薦就是這麼幹的,由於每個Fragment都寫一個接口,就會造成代碼冗餘;如果Fragment少的話還好,多的話,Activity實現多個接口,顯得Activity頭部很大,況且接口的命名也是一個問題;
二 萬能接口
如果在5的基礎能夠解決代碼冗餘、接口命名就好了,我們知道一個函數包括函數名、函數體、參數、返回值,那麼就可以通過搭建一個簡單的框架實現上述問題。
1 建立基類
public abstract  class Function {
/** 方法名 */
public String mFunctionName ;

public Function (String funName){
this.mFunctionName = funName;
}

}
2 建立無(有)參數無(有)四類
/**
* 無參無返回值
* <h3>Description</h3>
* TODO
* <h3>Author</h3> luzhenbang
* <h3>Date</h3> 2018/1/4 16:13
* <h3>Copyright</h3> Copyright (c)2018 Shenzhen TL Co., Ltd. Inc. All rights reserved.
*/

public abstract class FunctionNoParamNoResult extends Function {

public FunctionNoParamNoResult(String funName) {
super(funName);
}

public abstract void function();

}
/**
* 有參無返回值
* <h3>Description</h3>
* TODO
* <h3>Author</h3> luzhenbang
* <h3>Date</h3> 2018/1/4 16:13
* <h3>Copyright</h3> Copyright (c)2018 Shenzhen TL Co., Ltd. Inc. All rights reserved.
*/

public abstract class FunctionWithParamOnly<Param> extends Function {

public FunctionWithParamOnly(String funName) {
super(funName);
}

public abstract void function(Param param);


}
/**
* 有參有返回值
* <h3>Description</h3>
* TODO
* <h3>Author</h3> luzhenbang
* <h3>Date</h3> 2018/1/4 16:13
* <h3>Copyright</h3> Copyright (c)2018 Shenzhen TL Co., Ltd. Inc. All rights reserved.
*/

public abstract class FunctionWithParamWithResult<Result,Param> extends Function {

public FunctionWithParamWithResult(String funName) {
super(funName);
}

public abstract Result function(Param param);

}
/**
* 無參有返回值
* <h3>Description</h3>
* TODO
* <h3>Author</h3> luzhenbang
* <h3>Date</h3> 2018/1/4 16:13
* <h3>Copyright</h3> Copyright (c)2018 Shenzhen TL Co., Ltd. Inc. All rights reserved.
*/

public abstract class FunctionWithResultOnly<Result> extends Function {

public FunctionWithResultOnly(String funName) {
super(funName);
}

public abstract Result function();

}
3 建立管理器類
public class FunctionManager {

private static FunctionManager instance = null;
public static final String TAG = FunctionManager.class.getSimpleName() + "-------->";

/**容器,用來存儲方法名字 key 對應的方法名 value 對應的是 參數返回對象*/
private HashMap<String,FunctionWithParamWithResult> mFunctionWithParamWithResultHashMap = null;
private HashMap<String,FunctionWithParamOnly> mFunctionWithParamsOnlyHashMap = null;
private HashMap<String,FunctionWithResultOnly> mFunctionWithResultOnlyHashMap = null;
private HashMap<String,FunctionNoParamNoResult> mFunctionNoParamNoResultHashMap = null;


private FunctionManager() {
mFunctionNoParamNoResultHashMap = new HashMap<>();
mFunctionWithParamWithResultHashMap = new HashMap<>();
mFunctionWithParamsOnlyHashMap = new HashMap<>();
mFunctionWithResultOnlyHashMap = new HashMap<>();
}


public static FunctionManager getInstance() {
if (null == instance){
instance = new FunctionManager();
}
return instance;
}


/**
* 添加無參無返回值的方法
* @return
*/
public FunctionManager addFunction(FunctionNoParamNoResult function){
mFunctionNoParamNoResultHashMap.put(function.mFunctionName,function);
return this;
}


/**
* 添加有返回值的方法
* @return
*/
public FunctionManager addFunction(FunctionWithResultOnly function){
mFunctionWithResultOnlyHashMap.put(function.mFunctionName,function);
return this;
}


/**
* 添加有參數的方法
* @return
*/
public FunctionManager addFunction(FunctionWithParamOnly function){
mFunctionWithParamsOnlyHashMap.put(function.mFunctionName,function);
return this;
}



/**
* 添加有參有返回值的方法
* @return
*/
public FunctionManager addFunction(FunctionWithParamWithResult function){
mFunctionWithParamWithResultHashMap.put(function.mFunctionName,function);
return this;
}




/**
* 調用無返回值無參數的方法
* @param funName
*/
public void invokeNoAll (String funName) throws NullPointerException {
if (TextUtils.isEmpty(funName)){
Log.e(TAG,"funName is null !");
}else {
if ( null != mFunctionNoParamNoResultHashMap){
FunctionNoParamNoResult function = mFunctionNoParamNoResultHashMap.get(funName);
if (null != function){
function.function();
}else {
Log.e(TAG,"function is null !");
}
}else {
throw new NullPointerException("mFunctionNoParamNoResultHashMap can not be null ,please first init FunctionManager !");
}
}
}


/**
* 調用有參數的方法
* @param funName
*/
public <Param> void invokeWithParamOnly (String funName,Param param) throws NullPointerException {
if (TextUtils.isEmpty(funName)){
Log.e(TAG,"funName is null !");
}else {
if ( null != mFunctionWithParamsOnlyHashMap){
FunctionWithParamOnly<Param> function = mFunctionWithParamsOnlyHashMap.get(funName);
if (null != function){
function.function(param);
}else {
Log.e(TAG,"function is null !");
}
}else {
throw new NullPointerException("mFunctionWithParamsOnlyHashMap can not be null ,please first init FunctionManager !");
}
}
}




/**
* 調用有返回值的方法
* @param funName
*/
public <Result> Result invokeWithResultOnly (String funName, Class<Result> c) throws NullPointerException {
if (TextUtils.isEmpty(funName)){
Log.e(TAG,"funName is null !");
}else {
if ( null != mFunctionWithResultOnlyHashMap){
FunctionWithResultOnly function = mFunctionWithResultOnlyHashMap.get(funName);
if (null != function){
if ( null != c){
return c.cast(function.function());
}else {
return (Result) function.function();
}
}else {
Log.e(TAG,"function is null !");
}
}else {
throw new NullPointerException("mFunctionWithParamsOnlyHashMap can not be null ,please first init FunctionManager !");
}
}
return null;

}

/**
* 調用有參數有返回值的方法
* @param funName
*/
public <Result,Param> Result invokeWithAll (String funName, Class<Result> c,Param param) throws NullPointerException {
if (TextUtils.isEmpty(funName)){
Log.e(TAG,"funName is null !");
}else {
if ( null != mFunctionWithParamWithResultHashMap){
FunctionWithParamWithResult<Result,Param> function = mFunctionWithParamWithResultHashMap.get(funName);
if (null != function){
if ( null != c){
return c.cast(function.function(param));
}else {
return function.function(param);
}
}else {
Log.e(TAG,"function is null !");
}
}else {
throw new NullPointerException("mFunctionWithParamsOnlyHashMap can not be null ,please first init FunctionManager !");
}
}
return null;

}
}
4 在Activity寫一個方法
public void setFunctionForFragment(String tag){
if (TextUtils.isEmpty(tag)){
Log.e(MainActivity.class.getSimpleName(),"tag is null !");
return;
}
BaseFragment fragment = (BaseFragment) fm.findFragmentByTag(tag);
FunctionManager functionManager = FunctionManager.getInstance();

functionManager.addFunction(new FunctionNoParamNoResult(FunctionNoParamNoResult) {
@Override
public void function() {
Toast.makeText(MainActivity.this, "無參無返回值", Toast.LENGTH_SHORT).show();
}
});

functionManager.addFunction(new FunctionWithResultOnly<String>(FunctionWithResultOnly) {
@Override
public String function() {
return "無參有返回值";
}
});

functionManager.addFunction(new FunctionWithParamOnly<String>(FunctionWithParamOnly) {
@Override
public void function(String o) {
Toast.makeText(MainActivity.this, o, Toast.LENGTH_SHORT).show();
}
});

functionManager.addFunction(new FunctionWithParamWithResult<String,String>(FunctionWithParamWithResult) {
@Override
public String function(String o) {
return o;
}
});

fragment.setFunctionManager(functionManager);
}
5 編輯一個Fragment基類(實用Fragment的時候直接集成該類就可以了),並綁定上面建立的接口
public class BaseFragment extends Fragment{

public FunctionManager mFunctionManager;
private MainActivity mainActivity;

public void setFunctionManager(FunctionManager mFunctionManager) {
this.mFunctionManager = mFunctionManager;
}

@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof MainActivity) {
mainActivity = (MainActivity) context;
mainActivity.setFunctionForFragment(getTag());
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}

@Override
public void onDetach() {
super.onDetach();
mainActivity = null;
}

}
6 繼承BaseFragment
public class NoParamNoResultFragment extends BaseFragment {

private Handler mHandler;

public NoParamNoResultFragment(Handler handler) {
// Required empty public constructor
this.mHandler = handler;
}


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
}
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_no_param_no_result, container, false);

view.findViewById(R.id.txt_handle).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message message = mHandler.obtainMessage();
message.what = 0x123;
message.obj = "handle 通信";
mHandler.sendMessage(message);
}
});


view.findViewById(R.id.txt_noALl).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mFunctionManager.invokeNoAll(MainActivity.FunctionNoParamNoResult);

}
});
view.findViewById(R.id.txt_result).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// mFunctionManager.invokeNoAll(MainActivity.FunctionNoParamNoResult);
String result = mFunctionManager.invokeWithResultOnly(MainActivity.FunctionWithResultOnly,String.class);
Toast.makeText(getActivity(), result, Toast.LENGTH_SHORT).show();
}
});
view.findViewById(R.id.txt_param).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mFunctionManager.invokeWithParamOnly(MainActivity.FunctionWithParamOnly,"有參無返回值");
}
});
view.findViewById(R.id.txt_withAll).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String result = mFunctionManager.invokeWithAll(MainActivity.FunctionWithParamWithResult,String.class,"有參有返回值");
Toast.makeText(getActivity(), result, Toast.LENGTH_SHORT).show();
}
});
return view;
}
}
說明,上述在點擊控件的時候,會觸發在Activity添加的方法,這樣就可以實現Activity與Fragment實時通信,近而實現Fragment之間的通信。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章