最近一个版本的迭代有个需求就是黄金的金价需要实时刷新,最终确定用下面的方案,顺便总结了一下其他思路。
先直接看代码
首先使用单例创建对象,在单例里面注册了Evenbus ,这种写法不推荐,写了一个请求网络的方法,这个方法是在后面handler 中先去调用检查是否有监听者,如果有就使用handler 发送 还定义了添加移除监听的方式:
public class GoldPriceProvider implements IGoldPriceProvider {
private static final int ACTION_GOLD_REQUEST = 0x101010;
private static List<OnGoldPriceFreshListener> sSubscriber = new CopyOnWriteArrayList();
private Handler mHandler = new GoldFreshHandler();
/**
* 黄金刷新频率
*/
private static int GOLD_UPDATE_DURATION = 5 * 1000;
private static volatile GoldPriceProvider sGoldPriceProvider;
/**
* 默认黄金价格
*/
private GoldPrice mGoldPrice = new GoldPrice();
private GoldPriceProvider(){}
public static GoldPriceProvider getSingleton() {
if (sGoldPriceProvider == null) {
synchronized (GoldPriceProvider.class) {
if (sGoldPriceProvider == null) {
sGoldPriceProvider = new GoldPriceProvider();
EventBus.getDefault().register(sGoldPriceProvider);
}
}
}
return sGoldPriceProvider;
}
public GoldPriceProvider request(){
GoldMessageEvent.GoldPriceEvent event = new GoldMessageEvent.GoldPriceEvent();
GoldApi.fetchGoldPrice(new OnInnerRequestListener(event));
return this;
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onGoldPriceFetchedDone(GoldMessageEvent.GoldPriceEvent event){
int state = event.state;
Object result = event.result;
String errorTip = CommonUtils.getResponeErrorTip(BaseApplicationProxy.getApplicationContext(), state, result);
if (!TextUtils.isEmpty(errorTip)) {
return;
}
Response<GoldPrice> response = (Response<GoldPrice>) result;
GoldPrice price = response.data;
if(price != null){
this.mGoldPrice = price;
//如果接受黄金价格消息者不为零,则广播消息
if(checkActiveListener() >0) {
GOLD_UPDATE_DURATION = price.goldPriceRefreshInterval;
this.dispatch(price);
}
}
}
/**
* 注册黄金价格变动侦听接口
*
* @param listener
*/
public void addListener(OnGoldPriceFreshListener listener) {
Iterator<OnGoldPriceFreshListener> it = sSubscriber.iterator();
while (it.hasNext()) {
OnGoldPriceFreshListener reference= it.next();
if (listener == reference) {
return;
}
}
sSubscriber.add(listener);
mHandler.removeMessages(ACTION_GOLD_REQUEST);
mHandler.sendEmptyMessage(ACTION_GOLD_REQUEST);
}
private int checkActiveListener(){
return sSubscriber.size();
}
/**
* 分发时时金价,并且删除空订阅引用回调接口;
* @param price
*/
public void dispatch(GoldPrice price){
Iterator<OnGoldPriceFreshListener> it = sSubscriber.iterator();
while (it.hasNext()) {
OnGoldPriceFreshListener reference= it.next();
if (reference != null) {
reference.onGoldPriceRefreshed(price);
}
}
}
/**
* 移除黄金价格变动侦听接口
*
* @param listener
*/
public void removeListener(OnGoldPriceFreshListener listener) {
Iterator<OnGoldPriceFreshListener> it = sSubscriber.iterator();
while (it.hasNext()) {
OnGoldPriceFreshListener saved = it.next();
if (listener == saved) {
sSubscriber.remove(saved);
}
}
}
@Override
public GoldPrice getLatestGoldPrice() {
return mGoldPrice;
}
public class GoldFreshHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
request();
if(checkActiveListener()>0) {
mHandler.sendEmptyMessageDelayed(ACTION_GOLD_REQUEST, GOLD_UPDATE_DURATION);
}
}
}
}
上面的代码是有问题的,具体的问题就是使用了弱引用,这个在内存不足的时候,会把这个对象回收了,我们的监听就被干掉了,干掉了,实时刷新金价就不生效了。
更改为:
private static List<OnGoldPriceFreshListener> sSubscriber = new CopyOnWriteArrayList();
然后把正常调d代码也贴出:
@Override
protected void onResume() {
super.onResume();
GoldPriceProvider.getSingleton().addListener(this);
}
@Override
protected void onPause() {
super.onPause();
GoldPriceProvider.getSingleton().removeListener(this);
}
@Override
public void onGoldPriceRefreshed(IGoldPriceProvider.GoldPrice price) {
if(price == null ){
return;
}
this.mCurrentValueServer.setText(String.valueOf(price.goldPrice));
}
定时刷新方式1:
public class MainActivity extends Activity {
private TextView msg;
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
update();
break;
}
super.handleMessage(msg);
}
void update() {
//刷新msg的内容
}
};
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
msg = (TextView) findViewById(R.id.txtMsg);
msg.setText("你好啊!");
timer.schedule(task, 1000 * 40, 1000 * 30); //启动timer
}
@Override
protected void onDestroy() {
if (timer != null) {// 停止timer
timer.cancel();
timer = null;
}
super.onDestroy();
}
}
定时刷新方式2
1
public class MainActivity extends Activity {
2
private TextView msg;
3
private Handler handler = new Handler();
4
private Runnable runnable = new Runnable() {
5
public void run() {
6
this.update();
7
handler.postDelayed(this, 1000 * 120);// 间隔120秒
8
}
9
void update() {
10
//刷新msg的内容
11
}
12
};
13
/** Called when the activity is first created. */
14
@Override
15
public void onCreate(Bundle savedInstanceState) {
16
super.onCreate(savedInstanceState);
17
setContentView(R.layout.main);
18
msg = (TextView) findViewById(R.id.txtMsg);
19
msg.setText("你好啊!");
20javascript:void(null)
handler.postDelayed(runnable, 1000 * 60);
21
}
22
@Override
23
protected void onDestroy() {
24
handler.removeCallbacks(runnable); //停止刷新
25
super.onDestroy();
26
}
27
}
28
29
比较上面两种方式
第一种方式还适用于消息通知的方式实现更新,第二种方式通常是主动去检查是否需要刷新。对于定时刷新这种使用第二种方式更好
网友评论