技术类探讨--单个Handler解决一个应用刷新通知问题
2017-04-25 20:20
399 查看
熟知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() {@Overridepublic 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()) {@Overridepublic 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() {@Overridepublic void run() {((BasicLayout) view).onFreshModel((BasicModel) model);}});}}}}}};接收到消息后,再自动显示到对应的视图渲染器中,进行图层渲染。其实本质上讲,就是M V中提供一个接口方法,然后通过这个接口方法,进行数据刷新、数据处理,保证系统少用一些Handler,方便代码编写,代码就好比是一个模块孔槽,在对应的地方写入相关的业务,然后刷新、数据获取什么的都不必考虑。当然有些地方需要使用Handler的delay方式,可以在此基础上复用。新增一些消息即可。其实做法还有很多种,这里只是提供了一种方式,
相关文章推荐
- 创建并部署一个连接SQLAzure的WindowsAzure应用遇到的问题及解决办法
- 简单解决返回上一个Activity中的adapter数据刷新问题
- HttpModule和HttpHandler的一个小问题的解决
- 手机平台中QQ浏览器在页面中点击一个超链接会刷新整个页面问题解决
- 今天解决一个异步刷新TreeView的问题
- 最近做了一个iOS小应用,记录下遇到的问题以及解决方法
- 解决spring-cloud应用无法部署在同一个容器中的问题
- 多个依赖Netty3的应用在同一个Wildfly服务器上的布署冲突问题分析与解决
- 一个Android应用开发菜鸟的成长之路——工作第一天:解决了java.lang.NoClassDefFoundError问题
- ILOG OPL的一个简单应用——解决运输问题、转运问题
- 抢购是如今很常见的一个应用场景,主要需要解决的问题
- 《解决问题1000.1》又是I2C驱动问题,产品应用上一个问题,非常简单,也比较典型,记录一下
- 在IE里应用XML的一个小例子:解决双下拉选单的连动问题。
- 关于一个应用分枝界限法解决最小顶点覆盖问题的程序说明
- 解决angular单个页面只能加载一个ng-app的问题
- java__晓萌最近在做一个翻转图片的应用,你可能也知道,图片其实是由一个个的点组成的。于是,晓萌想先做一个可以翻转矩阵的程序,来解决他问题的核心部分。
- 一个“解决一个第三方应用一个功能打不开的问题”思路。
- ILOG的一个基本应用——解决运输问题、转运问题
- 在表示层禁用浏览器缓存的方法,以解决应用开发不能即时刷新体现修改结果的问题
- 一个实际问题分析及解决之九:什么是应用服务器