前言
最近在做一个小需求,是在一个listview的item上有一个区分性别的图片,和一个状态文本,如图:
在点击item的查看按钮时,进入下一个页面,如图:
该页面也有一个性别图片,和一个修改按钮,点击修改按钮展示一个dialog,里面可以选择性别,然后实时的更新页面,拿到需求后,本来想的是按照以往的做法,在请求成功后通过OnActivityforResult()方法,设置resultCode值,来刷新整个页面,但是在看到IOS同事得实现后,是直接单点刷新,虽然以前也知道Android可以实现,但是本人比较懒,一直没有去这么做。。。
本篇只是用的EventBus这个简单的框架,如果还没用过这个得伙伴,建议试用一下,相当不错,网上一大堆教程,我在这都给出来,省的大家再去找。
首先介绍下EventBus
EventBus是greenrobot在Android平台发布的一款以订阅——发布模式为核心的开源库。EventBus翻译过来是事件总线的意思,可以这样理解:一个个事件(event)发送到总线上,然后EventBus根据已注册的订阅者(subscribers)来匹配相应的事件,进而把事件传递给订阅者,这也是观察者模式的一个最佳实践。
那么EventBus可以用到什么地方呢?我们平时开发的时候,当遇到Activity与Activity、Activity与Fragment之间的通信,往往采用Intent,又或者线程之间使用Handler进行通信,这样代码难免会复杂许多,而使用EventBus能极大简化两个组件之间的通信问题,而且效率极高,而EventBus升级到3.0版本后,开发者能够自定义订阅方法的名字,而没必要规定以“onEventXX”开头的方法了,这样也自由化了很多,而且支持了粘性事件的分发等,因此学会使用EventBus3.0对我们的开发有极大的好处。
第一步:依赖包
去GitHub找EventBus地址
在Android Studio中添加如下依赖:
compile ‘org.greenrobot:eventbus:3.0.0’
第二步:使用
在准备好EventBus后,我们通过我的需求来展示它的使用方法。实现的例子很简单,主要是在Activity1中打开Activity2,而Activity2中通过点击按钮来使Activity1中的ImageView显示内容得到更改,而显示的内容由Activity2指定。这便构成了一个典型的Activity与Activity之间通信的场景,如果用我们之前的做法可以采用BroadcastReceiver来实现两者的通信,但现在我们使用EventBus,只需要几行代码就能实现了,而且还可以由Activity和Fragment之间的通信。具体使用我在后续代码中会告诉大家,我使用的是Activity和Fragment之间传值,
首先我在第二个页面Activity的dialog按钮选择性别并保存后,会调用一个接口,这个相信大家都会明白,然后在接口给我成功的结果后,用EventBus传递一个自己写的值如图:
EventBus.getDefault().post(new SubmitEvent(sex));该方法就是我传的值,很简单,这个SubmitEvent类是这样的:
public class SubmitEvent {
private String message;
public SubmitEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
就是一个很简单的字符串的自定义类
由于我的Fragment里面装载的是一个listview,所以单独把adapter抽取了出来了,所以下面的代码是adapter类里面的方法,首先我给这个item的点击事件跳转的时候把对应的position传过去,加粗的代码:
//点击填写操作
holder.tvStatus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
position = i;
if (firtCommunicate == 1){
FirstCommunicationActivity.open(context,model.studentId,”2”,model.year,model.term);
}else {
FirstCommunicationActivity.open(context,model.studentId,”“,”“,”“);
}
}
});
然后在该Fragment类里,在onCreateView方法里注册EventBus,加粗代码:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_new, null);//加载布局
EventBus.getDefault().register(this);// 注册EventBus
listView = (ListView) view.findViewById(R.id.list_view);
rootView = (ViewGroup) view.findViewById(R.id.rootView);
initView();//加载页面
return view;
}
再在onDestroy方法里去注销:
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);//注销EventBus
}
然后主要的代码就要登场了,下面的代码是接收传递过来的值,通用的方法,该方法就是接收EventBus传值的,是EventBus的方法
//订阅方法,当接收到事件的时候,会调用该方法
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(SubmitEvent messageEvent){
updateData(myAdapter.position , messageEvent.getMessage());
}
然后下面的代码就是更新要变化的view代码:
/**
* 单独更新组件
* @param position 更新组件的下标
*/
public void updateData(int position,String message) {
//获取对应position的数据
NewVersionNewStudentModel models = studentList.get(position);
//将传过来的值赋值给它
models.sex = message;
//获取当前显示项的第一行和最后一行
int firstVisible = listView.getFirstVisiblePosition();
int lastVisible = listView.getLastVisiblePosition();
//获取该行的view(因为listView仅会维护当前的显示项,所以根据下标获取时,0为当前显示行
// 的第一行即firstVisible,所以获取当前行应该用当前行减去firstVisible)
View view = listView.getChildAt(position - firstVisible);
if (view != null) { //若获取的时候该行被滑出屏幕则会返回空
//获取viewHolder
ImageView iv_sex = (ImageView) view.findViewById(R.id.iv_sex);//性别
//学生性别
if (null != message && !”“.equals(message)){
if (“1”.equals(message)){
iv_sex.setVisibility(View.VISIBLE);
iv_sex.setImageResource(R.mipmap.icon_man);
}else if (“0”.equals(message)){
iv_sex.setVisibility(View.VISIBLE);
iv_sex.setImageResource(R.mipmap.icon_women);
}else {
iv_sex.setVisibility(View.GONE);
}
}else {
iv_sex.setVisibility(View.GONE);
}
}
}
到这里整个功能就实现了,是不是第一眼看感觉很麻烦,其实很简单的,还有欢迎大家指正,希望能帮到需要的同学,和有更好的方法的也可以大家一起分享出来,谢谢!