app更新了有几个版本了,估计PM发现是时候优化一下细节了,统一一下标准。所以这期的需求里就有这么一项:统一所有页面的网络错误提示,同时不要影响现有的交互流程。
乍一看有20+的页面,作为一个比较懒的程序员,肯定不会想去每个页面单独实现,这样太傻,也难以接受。没准哪天PM又要大改,那就尴尬了。给未来的自己挖坑,而且还不得不跳,我是拒绝的。
为什么说是小技巧,其实思路很简单,就如同你在BaseActivity实现一些公共方法一样,添加公共的view也可以这样做。
看一下setContentView的实现
@Override
public void setContentView(View v) {
ensureSubDecor();
ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
contentParent.removeAllViews();
contentParent.addView(v);
mOriginalWindowCallback.onContentChanged();
}
@Override
public void setContentView(int resId) {
ensureSubDecor();
ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
contentParent.removeAllViews();
LayoutInflater.from(mContext).inflate(resId, contentParent);
mOriginalWindowCallback.onContentChanged();
}
@Override
public void setContentView(View v, ViewGroup.LayoutParams lp) {
ensureSubDecor();
ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
contentParent.removeAllViews();
contentParent.addView(v, lp);
mOriginalWindowCallback.onContentChanged();
}
当然了,没必要去深究更底层的实现,只需要知道系统拿到根布局的view,然后把我们自己写的view直接add进去。
所以这就提供了很大的扩展空间
思路很简单,先看一下自定义的xml文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
>
<include
layout="@layout/include_common_use_network_layout"
/>
<include
layout="@layout/include_common_use_nonedate_layout"
/>
</FrameLayout>
解释一下,两个include是我们项目中需要的网络错误页及数据错误页的布局,android:fitsSystemWindows="true"这句代码是我们做标题栏浸入的效果用到的。其实就是定义一个FrameLayout,把错误页的布局,及当前activity的布局都放进去。
下面是BaseActivity中相关代码的实现
public class BaseActivity extends AppCompatActivity implements View.OnClickListener {
private FrameLayout rootLayout;
private LinearLayout netErrorRoot,noneDateRoot;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
protected void setContentViewWithNetError(@LayoutRes int layoutResID) {
rootLayout = (FrameLayout) LayoutInflater.from(this).inflate(R.layout.root_layout,null);
netErrorRoot = (LinearLayout) rootLayout.findViewById(R.id.netErrorRoot);
noneDateRoot = (LinearLayout) rootLayout.findViewById(R.id.noneDateRoot);
View view = LayoutInflater.from(this).inflate(layoutResID,null);
rootLayout.addView(view,0);
rootLayout.findViewById(R.id.ib_net_error_click).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickForResponse();
}
});
super.setContentView(rootLayout);
}
protected void setTitleString(String title){
if (rootLayout == null)
return;
((TextView)rootLayout.findViewById(R.id.tvTitleNet)).setText(title);
((TextView)rootLayout.findViewById(R.id.tvTitleNone)).setText(title);
}
protected void setTitleResId(int id){
if (rootLayout == null)
return;
((TextView)rootLayout.findViewById(R.id.tvTitleNet)).setText(id);
((TextView)rootLayout.findViewById(R.id.tvTitleNone)).setText(id);
}
protected void showNetErrorLayout(){
if (rootLayout == null)
return;
netErrorRoot.setVisibility(View.VISIBLE);
}
protected void hideNetErrorLayout(){
if (rootLayout == null)
return;
netErrorRoot.setVisibility(View.GONE);
}
protected void showNoneDateLayout(String errorMsg){
if (rootLayout == null)
return;
noneDateRoot.setVisibility(View.VISIBLE);
((TextView)rootLayout.findViewById(R.id.tvErrorMsg)).setText(errorMsg);
}
protected void showNoneDateLayout(int errorMsg){
if (rootLayout == null)
return;
noneDateRoot.setVisibility(View.VISIBLE);
((TextView)rootLayout.findViewById(R.id.tvErrorMsg)).setText(errorMsg);
}
protected void hideNoneDateLayout(){
if (rootLayout == null)
return;
noneDateRoot.setVisibility(View.GONE);
}
protected void clickForResponse(){
}
}
逻辑比较简单,就不写什么demo了,直接把项目中的代码粘过来了,删除了一些与本文无关的东西。
很容易理解吧,在需要错误页提示的时候调用setContentViewWithNetError()方法,不需要的时候还是老套路用setContentView()方法,传的参数都一样。
通常无网情况下会有点击刷新,在上面的代码中,只需要在子activity重写clickForResponse()方法即可。其他的方法都是我们产品需要的一些实现,可看可不看。
有的人会说这回加深页面的渲染层级。说的好!的确会。
这种方法会在原有的基础上深度+1。其实在写这块的功能的时候也考虑过这种问题,也想过是不是可以直接在根布局上操作,后续可能会尝试一下;再有其实你的错误页面不需要在创建activity的时候就渲染的话,可以用viewstub来处理,减轻一点CPU和内存的压力,毕竟展示错误页面的情况还是比较少。姑且提出两种优化方案吧,大神请注意我的昵称(BaseCoder),不要拍!
当然了,类似统一的标题等一些类似的功能也可以这样处理。
网友评论