代替fragment的轻量级解耦UI的类:UIBlock

jopen 9年前

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


项目主页:http://www.open-open.com/lib/view/home/1444566421432