代替fragment的輕量級解耦UI的類:UIBlock
UIBlock
代替fragment的輕量級解耦UI的類
添加依賴
1.在項目外層的build.gradle中添加JitPack倉庫
repositories {
maven {
url "https://jitpack.io"
}
}2.在用到的項目中添加依賴
dependencies {
compile 'com.github.tianzhijiexian:UIBlock:1.0'
} 準備工作
在項目中建立一個BaseActivity,讓它實現ContainUIBlockActivity接口:
public class BaseActivity extends AppCompatActivity implements ContainUIBlockActivity{
private UIBlockManager mUIBlockManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUIBlockManager = new UIBlockManager(this);
}
@Override
public UIBlockManager getUIBlockManager() {
return mUIBlockManager;
}
@Override
public void onBackPressed() {
boolean handled = mUIBlockManager.onBackPressed();
if (!handled) {
super.onBackPressed();
}
}
@Override
public void onDestroy() {
super.onDestroy();
mUIBlockManager.onDestroy();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mUIBlockManager.onActivityResult(requestCode, resultCode, data);
}
}可以看到這里面就是在activity的回調時調用mUIBlockManager的對應的方法。這里其實還有一個思路就是用registerActivityLifecycleCallbacks這個方法,但是因為application只能設置一個監聽,如果開發者在自己的應用中也用了這個回調,我這里就監聽不到了。其次就是hook,但這里可能要引入一個框架,故沒嘗試。因此,還是采用比較搓的手動在生命周期中調用相應方法的辦法。
使用情形
1. 簡單劃分UI邏輯,降低Activity復雜度
我們之前用fragment來拆分UI的邏輯的辦法來提升程序可讀性,降低activity的復雜度。但因此帶來的是使用fragment出現的各種奇葩問題和fragment的復雜度。因此,我利用UIBlock實現了類似的功能,但復雜度遠遠降低。

比如我這里只想把頂部的這個linearLayout的邏輯獨立出來,但不想要獨立寫一個xml布局文件。要完成這個功能,我只需要建立一個UIBlock:
public class DemoTopUIBlock extends UIBlock{
@Override
public int getRootViewId() {
return R.id.top_ub;
}
TextView mTopTv;
@Override
protected void bindViews() {
mTopTv = getView(R.id.top_tv);
}
@Override
protected void setViews() {
String content = mTopTv.getText().toString();
mTopTv.setText(content + " :)");
}
}接著,在activity中getUIBlockManager().add(new DemoTopUIBlock()),這樣就使得這個linearLayout的邏輯轉交給了UIBlock。
2. 復用有相似界面和相似邏輯的UI
復用UI是很常見的需求,但這里我的意見是:多復用UI組件,而不是復用activity。因為如果activity被多次復用,可能會因為后面設計師的界面分化,造成維護的難度。
題外話說完了,來看看如何利用UIBlock做這樣的復用吧。這樣的復用很簡單,直接用現成的<include/>標簽即可,毫無技術性。

來看看被include的布局長啥樣(這里用到了tools:showIn這個小技巧): 
然后建立相應的UIBlock:
public class DemoBottomUIBlock extends UIBlock{
@Override
public int getRootViewId() {
return R.id.bottom_ub;
}
private EditText mBottomEt;
private Button mBottomBtn;
@Override
protected void bindViews() {
mBottomEt = getView(R.id.bottom_et);
mBottomBtn = getView(R.id.bottom_btn);
}
@Override
protected void setViews() {
mBottomBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity(DemoActivity.class).changeText();
}
});
}
public void onTextChangeCompleted(@NonNull String text) {
mBottomEt.setText(text);
}
}最后,在activity中引入這部分邏輯:getUIBlockManager().add(new DemoBottomUIBlock())
3. 嵌套使用UIBlock
之前豪哥(大神)提出過這樣的需求,activity中套fragment,這個fragment中又套了一個fragment,這種嵌套的問題在fragment的世界中真是令人頭疼。現在我們看看如何用UIBlock來簡單解決這個問題。

上面的代碼中,LinearLayout中嵌套了一個LinearLayout,我希望外面的LinearLayout被一個UIBlock控制,內部的LinearLayout被另一個UIBlock控制,形成嵌套。廢話不說,上外層的代碼:
public class DemoMiddleUIBlock extends UIBlock{
@Override
public int getRootViewId() {
return R.id.middle_ub;
}
@Override
protected void bindViews() {
getActivity(BaseActivity.class).getUIBlockManager().add(new DemoInnerUIBlock());
}
@Override
protected void setViews() {
getRootView().setBackgroundColor(0xff65a8b7);
}
} 這里重要的一個方法是:getActivity(),可以通過這個方法得到activity的對象,然后直接調用activity的getUIBlockManager()來引入內層嵌套的UIBlock就行了。至于DemoInnerUIBlock的代碼就不說了,和之前的類似。最后,不要忘記了在activity把這個UIBLock的代碼引入進來getUIBlockManager().add(new DemoMiddleUIBlock());。