俗话说,不想成为架构师的程序员不是好程序员。
封装的过程感觉就是一个发现,并且抽离的过程。需要时间和经验的积累,难以强求。心累不已。
在日常的开发中,Activity与Fragment是用到的最多的控件,里面必定会有些重复的代码,如果不加以复用,会让整个Activity和Fragment的代码显的臃肿不堪,总结一下学到的Activity与Fragment的最常用的封装方式。
整个Activity的一般都会有一些固定的流程,我们的目的就是为了抽离这些固定的逻辑,方便在子类中直接复用。
比如初始化控件的方法可以抽象成
protected void initWidget()
得到当前界面的资源文件Id的方法可以抽离成,
//方法必须是抽象的,我们要求子类必须继承此方法
protected abstract int getContentLayoutId();
另外还有初始化数据的方法可以抽离成
protected void initData()
以上情况是走我们的正常流程时才会触发,我们在进入界面的时候,必须确保我们传入的初始化参数是正确的才可以进行初始化,如果说传入的基本数据都不成功,我们也就没有必要初始化我们的基本数据了,所以需要一个方法
protected boolean initArgs(Bundle bundle)
另外我们知道,我们Window的初始化是不需要等到界面初始化完成之后才初始化的,所以对Window的初始化也需要一个方法
protected void initWidget()
最终我们的最重要的onCreate方法可能会成为这样
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 在界面未初始化之前调用的初始化窗口
initWidows();
if (initArgs(getIntent().getExtras())) {
// 得到界面Id并设置到Activity界面中
int layId = getContentLayoutId();
setContentView(layId);
initBefore();
initWidget();
initData();
} else {
finish();
}
}
另外可能还需要
// 当点击界面导航返回时,Finish当前界面
@Override
public boolean onSupportNavigateUp()
现在的开发情况一般都是Activity和Fragment相结合进行开发的,在处理后退的时候,我们不可能一个一个的处理,最好是复写Activity的
@Override
public void onBackPressed()
最终得到的我们自己的Activity可能会是这样
/**
* @author HFRX hfrx1314@qq.com
* @version 1.0.0
*/
public abstract class Activity extends AppCompatActivity {
protected PlaceHolderView mPlaceHolderView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 在界面未初始化之前调用的初始化窗口
initWidows();
if (initArgs(getIntent().getExtras())) {
// 得到界面Id并设置到Activity界面中
int layId = getContentLayoutId();
setContentView(layId);
initBefore();
initWidget();
initData();
} else {
finish();
}
}
/**
* 初始化控件调用之前
*/
protected void initBefore() {
}
/**
* 初始化窗口
*/
protected void initWidows() {
}
/**
* 初始化相关参数
*
* @param bundle 参数Bundle
* @return 如果参数正确返回True,错误返回False
*/
protected boolean initArgs(Bundle bundle) {
return true;
}
/**
* 得到当前界面的资源文件Id
*
* @return 资源文件Id
*/
protected abstract int getContentLayoutId();
/**
* 初始化控件
*/
protected void initWidget() {
ButterKnife.bind(this);
}
/**
* 初始化数据
*/
protected void initData() {
}
@Override
public boolean onSupportNavigateUp() {
// 当点击界面导航返回时,Finish当前界面
finish();
return super.onSupportNavigateUp();
}
@Override
public void onBackPressed() {
// 得到当前Activity下的所有Fragment
@SuppressLint("RestrictedApi")
List<Fragment> fragments = getSupportFragmentManager().getFragments();
// 判断是否为空
if (fragments != null && fragments.size() > 0) {
for (Fragment fragment : fragments) {
// 判断是否为我们能够处理的Fragment类型
if (fragment instanceof net.qiujuer.italker.common.app.Fragment) {
// 判断是否拦截了返回按钮
if (((net.qiujuer.italker.common.app.Fragment) fragment).onBackPressed()) {
// 如果有直接Return
return;
}
}
}
}
super.onBackPressed();
finish();
}
/**
* 设置占位布局
*
* @param placeHolderView 继承了占位布局规范的View
*/
public void setPlaceHolderView(PlaceHolderView placeHolderView) {
this.mPlaceHolderView = placeHolderView;
}
}
Fragment封装与Activity大同小异,个人感觉最终要的是处理Fragment的复用的问题,因为存在如下的情况,如果Fragment被回收,重新初始化Fragment的时候,有可能我们的mRoot还没被回收,那么他的Parent中就会有数据,所以我们要把它移除掉,另外,在我们监听返回键时,返回True代表我已处理返回逻辑,Activity不用自己finish。返回False代表我没有处理逻辑,Activity自己走自己的逻辑。
/**
* @author HFRX hfrx1314@qq.com
* @version 1.0.0
*/
public abstract class Fragment extends android.support.v4.app.Fragment {
protected View mRoot;
protected Unbinder mRootUnBinder;
protected PlaceHolderView mPlaceHolderView;
// 标示是否第一次初始化数据
protected boolean mIsFirstInitData = true;
@Override
public void onAttach(Context context) {
super.onAttach(context);
// 初始化参数
initArgs(getArguments());
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (mRoot == null) {
int layId = getContentLayoutId();
// 初始化当前的跟布局,但是不在创建时就添加到container里边
View root = inflater.inflate(layId, container, false);
initWidget(root);
mRoot = root;
} else {
if (mRoot.getParent() != null) {
// 把当前Root从其父控件中移除
((ViewGroup) mRoot.getParent()).removeView(mRoot);
}
}
return mRoot;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (mIsFirstInitData) {
// 触发一次以后就不会触发
mIsFirstInitData = false;
// 触发
onFirstInit();
}
// 当View创建完成后初始化数据
initData();
}
/**
* 初始化相关参数
*/
protected void initArgs(Bundle bundle) {
}
/**
* 得到当前界面的资源文件Id
*
* @return 资源文件Id
*/
@LayoutRes
protected abstract int getContentLayoutId();
/**
* 初始化控件
*/
protected void initWidget(View root) {
mRootUnBinder = ButterKnife.bind(this, root);
}
/**
* 初始化数据
*/
protected void initData() {
}
/**
* 当首次初始化数据的时候会调用的方法
*/
protected void onFirstInit() {
}
/**
* 返回按键触发时调用
*
* @return 返回True代表我已处理返回逻辑,Activity不用自己finish。
* 返回False代表我没有处理逻辑,Activity自己走自己的逻辑
*/
public boolean onBackPressed() {
return false;
}
/**
* 设置占位布局
*
* @param placeHolderView 继承了占位布局规范的View
*/
public void setPlaceHolderView(PlaceHolderView placeHolderView) {
this.mPlaceHolderView = placeHolderView;
}
}