美文网首页Android OtherAndroid开发经验谈Android开发
小技巧—BaseActivity添加公共的View,不再为网络错

小技巧—BaseActivity添加公共的View,不再为网络错

作者: BaseCoder | 来源:发表于2017-10-30 22:11 被阅读154次

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),不要拍!

当然了,类似统一的标题等一些类似的功能也可以这样处理。

相关文章

网友评论

    本文标题:小技巧—BaseActivity添加公共的View,不再为网络错

    本文链接:https://www.haomeiwen.com/subject/zlwmpxtx.html