Android元件化之不同模組間 互動(activity互相跳轉,資料互相傳遞,互相呼叫函式)
轉載請標明地址:https://blog.csdn.net/gaolei1201/article/details/77601027
在元件化之前,業務發展不是很快的時候,這樣是比較合適的,能一定程度地保證開發效率。
慢慢地程式碼量多了起來,開發人員也多了起來,業務發展也快了起來,或者由多個專案其實可以共用一些模組時,這時單一工程開發模式就會顯露出一些弊端:
- 耦合比較嚴重(因為沒有明確的約束,「元件」間引用的現象會比較多)
- 業務模組重用性較差
- 業務方的開發效率不夠高(只關心自己的元件,卻要編譯整個專案,與其他不相干的程式碼糅合在一起)
為了解決這些問題,就採取了「元件化」策略它能帶來這些好處:
- 加快編譯速度(不用編譯主客那一大坨程式碼了)
- 業務模組可以在不同專案中應用
- 方便QA有針對性地測試
- 提高業務開發效率
下面的這張圖是專案依賴關係
由於元件化的內容網上資料較多,我來講一些不一樣的。模組化是用來降低耦合度,但是有時候難免會和其他模組有些互動(這也是自己在公司開發專案中遇到的) ,一個模組可以呼叫被依賴模組的類方法,而被依賴模型不能引入依賴模組類。簡而言之就是,依賴只能單向,不能是雙向,就算你想Android Studio也不讓。但有時候被依賴的模組也需要一些依賴模組的資料怎麼辦?我就講一下不同模組之間怎麼互動的。
一、Activity之間跳轉,有幾種方式:
1.隱式Intent,要跳轉的活動在Manifest.xml中宣告,然後呼叫startActivity(new Intent(“com.example.boost”))
<activity android:name="com.example.boost.BoostActivity">
<intent-filter>
<action android:name="com.gaolei" />
</intent-filter>
</activity>
2. manifest.xml中活動的資料設計URI來接受跳轉,然後呼叫startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse(“activity:// applock”)))。更多內容可瞭解路由器:
<activity
android:name=".module.ui.activity.RecommendGuideActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="activity" />
<data android:host="applock" />
</intent-filter>
</activity>
3.利用反射
Class clazz=Class.fromName("com.clean.spaceplus.MainActivity")
startActivity(this,clazz);
如圖4所示,可以看演示中的程式碼,就是把不同模組的一些類註冊到一個都依賴的模組(如專案中的介面的ModuleDelegate),然後一個模組就可以電子雜誌到其他模組的一些類物件,從而呼叫那個類的方法進行一些操作,如跳轉一些活動。
下面是ModuleDelegate來註冊不同模組的一些類,供其他模組呼叫
public class CleanDelegate {
private final Map<String, IDelegateFactory> factoryMap = new HashMap<>();
private static final CleanDelegate mInstance = new CleanDelegate();
private CleanDelegate() {
}
public static CleanDelegate getInstance() {
return mInstance;
}
public static void register(String key, IDelegateFactory factory) {
mInstance.factoryMap.put(key, factory);
}
public Bundle getData(String factoryCode, int code, Bundle args, Object... extras) throws DelegateException {
IDelegateFactory factory = factoryMap.get(factoryCode);
if (factory != null) {
IDataDelegate transfer = factory.getDataTransfer(code);
if (transfer != null) {
return transfer.getData(args, extras);
}
}
throw new DelegateException("unknow data transfer");
}
}
4. 推薦使用第三方框架ActivityRouter,詳情可搜尋相關文章
二、模組間如何通訊,也有幾種方法
1. 推薦使用第三方框架EventBus,詳情可搜尋相關文章
2. 就是把不同模組的一些類註冊到一個都依賴的模組(如專案中的介面的ModuleDelegate),然後一個模組就可以電子雜誌到其他模組的一些類物件,從而呼叫那個類的方法進行一些操作,如獲取一些資料。
下面這個類是防毒軟體模組呼叫升壓模組的一些資料
public class AntivirusActivity extends Activity {
TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_submodule2);
text = findViewById(R.id.text);
}
public void getDataFromOtherModule(View view) {
Bundle bundle;
try {
bundle = new Bundle();
bundle.putString("gaolei", "beauty");
Bundle bundle1 = ModuleDelegate.getInstance().getData(BoostDelegateConsts.FACTORY, BoostDelegateConsts.DataCode.getTotalMemoryByte, bundle, AntivirusActivity.this);
String result = bundle1.getString("result");
text.setText(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. 如果呼叫其他模組的一些方法是執行一些耗時操作,那麼我們就可以在其他模組的子執行緒中傳送廣播,這個模組來接受。廣播不管是不是在子執行緒中都可以傳送出去,關於廣播是最基本的我就不多說
/**
* @author gaolei
* @Description:供Antivirus模組呼叫的類
*
*/
public class GetSyncData implements IDataDelegate {
@Override
public Bundle getData(Bundle args, Object... extras) throws DelegateException {
if (extras.length > 0 && extras[0] != null) {
if (extras[0] instanceof Context) {
final Context context = (Context) extras[0];
new Thread() {
public void run() {
try {
new Thread() {
public void run() {
try {
//模擬耗時操作,在這個執行緒裡可以做耗時操作,然後把資料通過廣播傳出去
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Bundle bundle = new Bundle();
bundle.putString("result", "這是一條非同步獲取的資料從Boost模組");
Intent intent = new Intent("com.example.getdata");
intent.putExtras(bundle);
context.sendBroadcast(intent);
}
}.start();
} catch (Throwable e) {
}
}
}.start();
}
}
return null;
}
}
public class AntivirusActivity extends Activity {
TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_antivirus);
text=findViewById(R.id.text);
IntentFilter filter=new IntentFilter("com.example.getdata");
DataReceiver dataReceiver=new DataReceiver();
registerReceiver(dataReceiver,filter);
}
public void getDataFromOtherModule(View view) {
Bundle bundle;
try {
bundle = new Bundle();
bundle.putString("gaolei", "beauty");
Bundle bundle1= ModuleDelegate.getInstance().getData(BoostDelegateConsts.FACTORY, BoostDelegateConsts.DataCode.getTotalMemoryByte,bundle,AntivirusActivity.this);
String result=bundle1.getString("result");
text.setText(result);
} catch (Exception e) {
e.printStackTrace();
}
}
public void getSyncDataFromOtherModule(View view) {
Bundle bundle;
try {
bundle = new Bundle();
//這個地方是呼叫Boost模組,獲取非同步資料
Bundle bundle1= ModuleDelegate.getInstance().getData(BoostDelegateConsts.FACTORY, BoostDelegateConsts.DataCode.getSyncData,bundle,AntivirusActivity.this);
} catch (Exception e) {
e.printStackTrace();
}
}
public class DataReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle=intent.getExtras();
String data=bundle.getString("result");
text.setText(data);
}
}
}