Android Fragment、Activity、Dialog 各种组件直接数据共享,更新通知

     我要放大招了,纠结了两个礼拜的一个问题,让师傅几分钟写了一堆代码轻松就搞定了,再次非常感谢阿博师傅,之前两个月的代码很多都是他帮了很大的忙,我就是一个总结,总想着这些问题,在百度了一大圈都没有很好的解决方案之后,我解决了,就想分享给和我遇到同样的问题的同行业的,不管你是大牛还是菜鸟,都可以提出建议,我所有的解决方案都是基于解决实际问题而出发的,所以很多时候没有考虑扩展性或者复用性、效率这些问题,欢迎提出建议,共同进步。

         有点扯远了,回到正题好了,详细描述如下:相信很多人都会使用下拉列表、对话框、弹出框、自定义对话框、等等其他的时间控件之类的组件,有时候会有这样的需求:   下拉列表选中的数据或者自定义的组件选中的数据,要返回到原来的界面(也就是你点击了某一个按钮或者textview,弹出的自定义的Activity、Fragment等),这些数据需要从对话框等组件返回到主界面,用来完成其他的逻辑,那么有多少方案可以完成这个需求呢?。。。。

      以下是针对于DatePicker日期选择组件,选择某一个日期之后,返回用户选择的日期到主界面,进行逻辑处理:

       第一种方案是针对普通情况,可以使用一个类,专门保存数据,写好Setter/Getter方法,也算是一种组件的思想。大概的过程很简单:在用户选择某一个时间之后,使用该类的setter方法,设置这个变量的值,然后在主界面需要该变量值的地方使用Getter方法,得到数据,进而进行处理。

       第一步:设置一个保存通用变量的类:DocCaptain.java   (因为是公司的代码,所以抱歉不能给出完整的代码,只能贴出关键代码

   

package client.verbank.mtp.allone.doc;

import jedi.verbank.CSTS3.comm.struct.AccountBasic;
public class DocCaptain {

	private static DocCaptain instance;

       //这个是日期控件用户选中的具体日期,可以放在里面,随时拿出来用
	private String addPriceTime;

	public String getAddPriceTime() {
		return addPriceTime;
	}

	public void setAddPriceTime(String addPriceTime) {
		this.addPriceTime = addPriceTime;
	}

}
     第二步,在使用的类中,这样使用:

package client.verbank.mtp.allone.frame.price.tipsprice.addtipsprice;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class AddTipsPriceFragment extends<span style="color:#ff0000;"><strong> Fragment</strong></span> {

	String timeAddPrice;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View vi = inflater.inflate(R.layout.activity_tipsprice_addtipsprice,
				container, false);
		if (flag == 0) {
			List<Instrument> list = APIDoc.getSystemDocCaptain()
					.getInstrumentList();
			instrument = list.get(0).getInstrument();
			DocCaptain.getInstance().setTipspriceInstrument(instrument);
			flag = 1;
		} else {

			instrument = DocCaptain.getInstance().getTipspriceInstrument();
			        timeAddPrice = DocCaptain.getInstance().getAddPriceTime();
                                timeView = (TextView) arg1;
String initDateTime = "2015-9-7 12:22";
DateTimePickDialogUtil dateTimePicKDialog = new DateTimePickDialogUtil(
getActivity(), initDateTime);
dateTimePicKDialog.dateTimePicKDialog();
		}
	}

}

        第三步:弹出日期控件的代码就不贴出来了,百度上有很多前辈已经写好了的。

      

       总结一下,第一种方案,可以应用的范围:如果共享的数据不多,并且不是很多开发人员使用(因为会有并发操作的可能)。还有应用场景是:当从日期控件选择确定之后,可以通过Intent,将取到的数据传递给需要的主界面。我相信很多都能明白,也非常容易实现。应用范围很小,是有很多弊端性,但是避免了很多没必要的代码,更易于管理。不需要使用android sharedpreferences,以及数据库sqlite,在每个界面获取共享的数据,简化了代码。

      还有一个最重要的弊端是,在以下应用场景下,上述的方案无法完成想要的需求,具体描述如下:

       就是我的这个手机项目,看过之前我之前的博客的人都知道,我用的是下拉菜单,切换fragment,也就是通过替换主界面的Textview来实现,切换不同的fragment,利用fragmentmanager来管理,隐藏和显示。  

       实际的场景是这样的:有一个下拉spinner,有一个数组让用户选择的是有效期限,有一个特殊的选项是:自定义时间,需要点击下拉列表的:“自定义时间”这个列表项,点击之后跳转到 日期控件的界面,这时候用户选择了一个合适的时间,点击设置之后,日期对话框消失了,这时候,需要将用户选择的时间返回到该  Fragment,一个很棘手的问题来了:   对话框消失之后,如何能监听,并且拿到该数据?使用第一种方案,无法触发这个事件,返回之后无法执行设置下列spinner显示的内容,这样就出现了第二种终极方案:   

            

             第二种方案:                              使用通用事件监听,当一个事件发生之后,通知给已经注册的类,拿到所需要的信息,并自己进行处理

    
             我稍微加一点自己的理解:举个例子,当老师在黑板上写了一行数字,坐在下面的A 、B、C三个同学接收到老师看黑板的指令之后,就记下了这串数字,A拿到这串数字就写在本子上了,B看到这串数字,没什么感觉,C则在原来的基础上加了几个字。过了几分钟,老师重新擦掉了原来的一串数字,写了一首诗,老师提醒各位同学,黑板上内容已经变了,各位同学注意了,重新摘抄一遍。大概的流程就是这样:首先所有同学必须是这个班上的,所以需要先向老师报道(也就是注册,否则我怎么知道教哪些学生),老师发布内容,告诉同学们黑板上有新的内容(也就是通知每个同学这个事件已经发生了,想要的可以拿去处理)。

            第一步:写一个通用的事件监听处理的方法,总共有4个类:



                          (A) IStationEventName.java

package client.verbank.mtp.allone.event;

public interface IStationEventName {

	String EVENT_NAME_TIME_CHANGE = "EVENT_NAME_TIME_CHANGE";
}
                       (B)StationEventCaptain.java

package client.verbank.mtp.allone.event;

import java.util.ArrayList;
import java.util.EventListener;
import java.util.HashMap;
import java.util.List;

public class StationEventCaptain {

	private static StationEventCaptain instance;

	private HashMap<String, List<EventListener>> eventMap = new HashMap<String, List<EventListener>>();

	public static StationEventCaptain getInstance() {
		if (instance == null) {
			instance = new StationEventCaptain();
		}
		return instance;
	}

	public void fireEventDataChange(String eventName) {
		fireEventDataChange(new StationEventData(eventName));
	}

	public void fireEventDataChange(StationEventData eventData) {
		synchronized (eventMap) {
			if (eventMap.containsKey(eventData.getEventName())) {
				List<EventListener> eventList = eventMap.get(eventData
						.getEventName());
				for (EventListener eventListener : eventList) {
					StationEventListener stationEventListener = (StationEventListener) eventListener;
					stationEventListener.onDataEvent(eventData);
				}
			}
		}
	}

	public void addEventDataChangeListener(StationEventListener listener,
			String eventName) {
		synchronized (eventMap) {
			if (eventMap.containsKey(eventName)) {
				List<EventListener> eventList = eventMap.get(eventName);
				eventList.add(listener);
			} else {
				List<EventListener> eventListenerList = new ArrayList<EventListener>();
				eventListenerList.add(listener);
				eventMap.put(eventName, eventListenerList);
			}
		}
	}

	public void removeEventDataChangeListener(StationEventListener listener,
			String eventName) {
		synchronized (eventMap) {
			if (eventMap.containsKey(eventName)) {
				List<EventListener> eventList = eventMap.get(eventName);
				eventList.remove(listener);
			}
		}
	}
}

               (C)StationEventData.java

package client.verbank.mtp.allone.event;

public class StationEventData {

	private String eventName;

	private Object data;

	public StationEventData() {
		super();
	}

	public StationEventData(String eventName) {
		super();
		this.eventName = eventName;
	}

	public StationEventData(Object data) {
		super();
		this.data = data;
	}

	public StationEventData(String eventName, Object data) {
		super();
		this.eventName = eventName;
		this.data = data;
	}

	public String getEventName() {
		return eventName;
	}

	public void setEventName(String eventName) {
		this.eventName = eventName;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}

}

           (D)StationEventListener.java

package client.verbank.mtp.allone.event;

import java.util.EventListener;

public interface StationEventListener extends EventListener {

	public void onDataEvent(StationEventData data);
}
            上述的代码完全可以复用的,可以直接复制黏贴到你的工程代码里面,相当于一个UTIL工具类。接下来就得使用了,首先在fragment里面注册一个事件,告诉他我是你的同学,等老师写了字的时候告诉我,并且重写接口里面的消息方法,我拿到这串数字,我要自己处理,别人管不着。代码片段如下:

package client.verbank.mtp.allone.frame.price.tipsprice.addtipsprice;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

//价格提示

public class AddTipsPriceFragment extends ControlFragment implements
		StationEventListener {

	。。。。。。。。。。

	private String instrument;

//注册监听事件
	public AddTipsPriceFragment(MainActivity activity) {
		super(activity);
		StationEventCaptain.getInstance().addEventDataChangeListener(this,
				IStationEventName.EVENT_NAME_TIME_CHANGE);
	}
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View vi = inflater.inflate(R.layout.activity_tipsprice_addtipsprice,
				container, false);
		if (flag == 0) {
			List<Instrument> list = APIDoc.getSystemDocCaptain()
					.getInstrumentList();
			instrument = list.get(0).getInstrument();
			DocCaptain.getInstance().setTipspriceInstrument(instrument);
			flag = 1;
		} else {

			instrument = DocCaptain.getInstance().getTipspriceInstrument();
			timeAddPrice = DocCaptain.getInstance().getAddPriceTime();
		}

		initComponent(vi);

		setEffectDataForSpinner(vi);

		refreshUI();

		return vi;
	}

	。。。。。。。。。。。
	

	// 使用数组形式操作
	class effectivedateSpinnerSelectedListener implements
			OnItemSelectedListener {

		@Override
		public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
				long arg3) {
			switch (arg2) {
			
			case 9:
				/*
				 * 跳转到日期控件选择界面
				 */
				timeView = (TextView) arg1;
	String initDateTime = "2015-9-7 12:22";
	DateTimePickDialogUtil dateTimePicKDialog = new DateTimePickDialogUtil(
						getActivity(), initDateTime);
				dateTimePicKDialog.dateTimePicKDialog();

				break;

			default:
				break;
			}

			// Toast tst = Toast.makeText(getView().getContext(), "您点击了" +
			// m[arg2]
			// + "第" + arg2 + "项", Toast.LENGTH_SHORT);
			// tst.show();

		}
。。。。。。。。。。。。。。。
	}

	。。。。。。。。。
	// 当界面隐藏之后重新show,监听
	@Override
	public void onHiddenChanged(boolean hidd) {
		if (hidd) {

		} else {
			if (tipsprice_inst != null) {
				tipsprice_inst.setText(DocCaptain.getInstance()
						.getTipspriceInstrument());
			}
			instrument = DocCaptain.getInstance().getTipspriceInstrument();
			timeAddPrice = DocCaptain.getInstance().getAddPriceTime();

		}
	}

。。。。。。。。。。。

	@Override
	public int getFramentKey() {
		return IBundleCommData.FRAGMENT_ID_ADDTIPSPRICE;
	}
。。。。。。。。。。。。。
//自己对消息自行处理的方法
@Override
	public void onDataEvent(final StationEventData data) {
		System.out.println(data.getData() + " ==============================");
		if (timeView != null) {
			Runnable work = new Runnable() {

				@Override
				public void run() {
					timeView.setText(data.getData().toString() + ":00");
				}
			};
			getHandler().post(work);
		}
	}</strong></span>
}

        至此就结束了,对于上述的代码不完整做一个解释,因为是公司的代码,不能贴出全部的代码,但核心代码已经贴出来了,讲的很模糊,有大牛的话可以指出错误。希望对同样 使用fragment 来开发界面的同学,对于数据共享和通知更新有一个新的解决方案,共同进步。

     欢迎有同样的问题,咨询。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值