代替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());。