技术类探讨--单个Handler解决一个应用刷新通知问题

来源:互联网 发布:c语言中合法的标识符 编辑:程序博客网 时间:2024/06/03 18:36

熟知Android的童鞋一定对Handler不陌生,Android的Handler可以进行UI Thread和普通Thread之间的数据交互操作。笔者喜欢用一个Handler解决一个Application之间的线程通信问题。这样做的方式,可以降低每个Activity和Fragment之间Handler的创建数量。尽可能的优化代码。

笔者从嵌入式转行做Android也有些时日了,参考了某国内股票公司的一些设计思想,配置+复用的思想沿用至今。对于一个Application尽可能的考虑少写代码多做功能。程序好比是搭积木,一个一个小的模块,组合成不同的应用。具体采用了观察+注册的思想模式,每个业务都在系统注册一个唯一的标识作为业务代码模块的核心,然后通过系统调用的方式,调度到某一个、某一级别的业务层代码。

如下所示的代码基础类方式,比如Activity为例:

public abstract class BasicActivity<M, V> extends AppCompatActivity implements LDNetDateCallback {        private                Handler mHandler                    = new Handler(Loop.getMainLoop());    private       LDDataSetObserver mServer;    protected     V                 mView;    protected     M                 mModel;    protected     int               mIds;  //业务系统ID    private       View              headerView;        @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {
//封装通用组件,比如title,底部导航栏,等等通用组件工具,用动态加载的方式实现。    }    public View getHeaderView() {        return headerView;    }    private void registSystem() {        registActivity();    }    protected void onCreateActivity(Bundle savedInstanceState) {    }    private void registActivity() {        IntentFilter filter = new IntentFilter();        filter.addAction(MSG_LOGOUT);        filter.addAction(MSG_NETWORK_ERROR);        filter.addAction(MSG_SERVICE_START);        filter.addAction(MSG_SERVICE_STOP);        registerReceiver(this.mBroadcastReceiver, filter); // 注册    }    /**     * 方法描述:     * <p/>     * 参数:     * 返回:     * 创建人:Genesis     * 创建时间:16/5/19     * 修改备注:     *     * @version     */    public void setLeftBtnVisable(int isVisable) {    }    public V getControllerView() {        return mView;    }    public void setControllerView(V mView) {        if (mServer != null) {            mServer.setView(mView);        }        this.mView = mView;    }    public M getModel() {        return mModel;    }    public void setModel(M mModel) {        if (mServer != null) {            mServer.setModel(mModel);        }        this.mModel = mModel;    }    /**     * 方法描述:     * 设置右边按键的可见性     * 参数:     * 返回:     * 创建人:Genesis     * 创建时间:16/9/13     * 修改备注:     *     * @version     */    public void setRightBtnVisable(int isVisable) {        if (mTitleBar != null) {            mTitleBar.setRightVisable(isVisable == View.VISIBLE);        }    }    /**     * 方法描述:     * 显示等待框Dialog     * <p>     * 参数:     * 返回:     * 创建人:Genesis     * 创建时间:16/9/13     * 修改备注:     *     * @version     */    protected void showWait(String msg) {           }    @Override    protected void onResume() {        super.onResume();    }    /**     * 方法描述:     * 取得titlebar相关控件的引用     * 参数:     * 返回:     * 创建人:Genesis     * 创建时间:16/9/13     * 修改备注:     *     * @version     */    public TitleBar getTitleBar() {        return mTitleBar;    }    /**     * 隐藏dialog框     */    protected void hideWait() {          }    /**     * 方法描述:     * 设置title     * 参数:     * 返回:     * 创建人:Genesis     * 创建时间:16/9/13     * 修改备注:     *     * @version     */    protected void setTitle(String title) {        mTitleBar = (TitleBar) findViewById(R.id.title_bar);        if (mTitleBar != null) {            mTitleBar.setTitle(title);            mTitleBar.invalidate();        }    }    /**     * 方法描述:     * 设置做标题监听事件     * 参数:     * 返回:     * 创建人:Genesis     * 创建时间:16/9/13     * 修改备注:     *     * @version     */    public void setTopLeftBtnListener(View.OnClickListener onClickListener) {        setLeftBtnVisable(View.VISIBLE);        if (mTitleBar != null) {            mTitleBar.setLeftClickListener(onClickListener);        }    }    /**     * 方法描述:     * 设置右标题     * 参数:     * 返回:     * 创建人:Genesis     * 创建时间:16/9/13     * 修改备注:     *     * @version     */    public void addRightBtnAction(TitleBar.Action action) {        setRightBtnVisable(View.VISIBLE);        if (mTitleBar != null) {            mTitleBar.addAction(action);        }    }    public int getIds() {        return mIds;    }    public void setIds(int mIds) {        this.mIds = mIds;    }    /**     * 方法描述:     * 清楚所有Action     * 参数:     * 返回:     * 创建人:Genesis     * 创建时间:16/9/13     * 修改备注:     *     * @version     */    public void clearRightBtnAction() {        if (mTitleBar != null) {            mTitleBar.removeAllActions();            mTitleBar.invalidate();        }    }    @Override    protected void onDestroy() {        super.onDestroy();        BasicApplication.getSysApplication().notifyDataInvalidated();        BasicApplication.getSysApplication().unregisterDataSetObserver(mServer);    }    public boolean hasLollipop() {        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;    }    protected int getObserverId() {        if (mServer == null) {            return mIds;        }        return mServer.getIds();    }    protected abstract void initView();    protected abstract int onCreateViewResID();}
总体的设计思想,一个ID对应一个业务模块,每个Activity中有一个注册机制,在系统Application中注册相应的ID,然后当系统侦测到对应的数据,会做相应的函数调度。主要采用MVC的设计方式,Mode负责数据业务解析,View做视图渲染方面。提供一些基本的函数入口,比如:

public abstract class BasicLayout<T> extends LinearLayout {    public BasicLayout(Context context) {        super(context);    }    public BasicLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    public BasicLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    /**     * 方法描述:     * 框架自动处理Model数据     * 参数:     * 返回:     * 创建人:Genesis     * 创建时间:16/10/22     * 修改备注:     *     * @version     */    public abstract void onFreshModel(T model);}

比如在View中,实现一个onFreshModel接口,实现model的插入,所要的数据都对该model数据进行翻译。model中可以提供相应的方法。用于数据解析,不过笔者在这里的操作是通过Handler调用。

   if (mModel != null) {        if (mModel instanceof BasicModel) {            new Thread(new Runnable() {                @Override                public void run() {                    ((BasicModel) mModel).parseParam(param);                    mController.onChanged(mModel);                    Message message = new Message();                    message.what = Constant.MSG_VIEW_REFRESH;                    LDDataSetObject object = new LDDataSetObject(mModel, mView);                    message.obj = object;                    mHandler.sendMessage(message);                }            }).start();        }    }    mController.onChanged(param);}
在回调地方新建一个线程处理业务代码,可以是二进制流也可以是其它的对象,然后用model进行数据处理。最后发送到系统主要单利全局Handler中进行数据刷新。

/** * 方法描述: * 系统调度刷新业务接口 * 参数: * 返回: * 创建人:Genesis * 创建时间:16/10/21 * 修改备注: * * @version */protected static Handler mHandler = new Handler(Looper.getMainLooper()) {    @Override    public void handleMessage(Message msg) {        super.handleMessage(msg);        if (msg.what == Constant.MSG_VIEW_REFRESH) {            if (msg.obj instanceof LDDataSetObject) {                LDDataSetObject object = (LDDataSetObject) msg.obj;                final Object model = object.getModel();                final Object view = object.getView();                if (view != null) {                    if (view instanceof BasicLayout) {                        mHandler.post(new Runnable() {                            @Override                            public void run() {                                ((BasicLayout) view).onFreshModel((BasicModel) model);                            }                        });                    }                }            }        }    }};
接收到消息后,再自动显示到对应的视图渲染器中,进行图层渲染。其实本质上讲,就是M V中提供一个接口方法,然后通过这个接口方法,进行数据刷新、数据处理,保证系统少用一些Handler,方便代码编写,代码就好比是一个模块孔槽,在对应的地方写入相关的业务,然后刷新、数据获取什么的都不必考虑。当然有些地方需要使用Handler的delay方式,可以在此基础上复用。新增一些消息即可。

其实做法还有很多种,这里只是提供了一种方式,

0 0
原创粉丝点击