代替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());
。
Jack Tony: developer_kale@qq.com
Copyright 2015 Jack Tony
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.