今天刚好在写一个在线二维码的刷新,每间隔1分钟进行刷新,android的机制导致了如果android App在后台运行的化,会一直走,这样用户的流量什么的完全耗不起,顾有了下面的小小研究。
导致流量走的比较快的原因如下:
1.访问数据的流量,这个和后端接口查询等有很大的关系,然而本宝并不能怎么样,这里接口端的兄弟可以优化下。
2.多次访问数据会导致流量使用比较多
作为android开发,研究点就在这里的访问次数了,有了方向,应该比较好容易优化了happy,因为本人使用的访问数据框架为 OKHTTp+RXAndroid等观察模式的数据访问框架,顾已经对,请求错误超时等做过一系列的处理。
/***
* 倒计时
*/
private CountDownTimer timer = new CountDownTimer(6000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
timerIsStart = true;
Logs.d(TAG, "倒计时开始--------------->");
}
@Override
public void onFinish() {
Logs.d(TAG, "timer is onFinish");
timerIsStart = false;
timer.cancel();
//完成之后
getNetData();
}
};
比较简单粗暴的方式,这里的getNetData();为本人的一个拉取数据的处理
/***
* 拉取网络数据
*/
private void getNetData() {
Logs.d(TAG, "getNetData()---------------->");
Logs.d(TAG, "data is :" + bundle_data + ",id:" + bundle_data.getBusinessId());
if (bundle_data != null && !StringUtlis.isEmpty(bundle_data.getBusinessId())) {
String company = "", groupShortName = "", businessId = "", miniLogo = "";
if (!StringUtlis.isEmpty(bundle_data.getCompany())) {
company = bundle_data.getCompany();
}
if (!StringUtlis.isEmpty(bundle_data.getMiniLogo())) {
miniLogo = bundle_data.getMiniLogo();
}
businessId = bundle_data.getBusinessId();
groupShortName = bundle_data.getGroupShortName();
NetService.getInstance().getScanDiscount(company, groupShortName, businessId, miniLogo, new Observer() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(CommResultBeanVo value) {
timeStamp = System.currentTimeMillis();
ScanDiscountBean data = new ScanDiscountBean();
if (value != null && !StringUtlis.isEmpty(value.getData())) {
data = new Gson().fromJson(value.getData(), ScanDiscountBean.class);
Logs.d(TAG, "value.getData() is " + value.getData());
}
scanDiscountBean = data;
if (data != null) {
if (!StringUtlis.isEmpty(data.getDimensionCodeForShow())) {
if (jifenTxt.getText() != null && !StringUtlis.isEmpty(jifenTxt.getText().toString())
&& jifenTxt.getText().toString().indexOf("*") == -1) {
jifenTxt.setText(data.getAvailablePoint());
}
}
if (!StringUtlis.isEmpty(data.getDimensionCodeForShow())) {
qrCodeNumber.setText(data.getDimensionCodeForShow());
}
if (!StringUtlis.isEmpty(data.getDimensionCode())) {
String dimensionCode = data.getDimensionCode();
//条形码
Bitmap barCodeBitmap = QRCodeUtil.creatBarcode(activity,
dimensionCode, (int) barCodeWidth, (int) barCodeHeight, false);
barCodeImg.setImageBitmap(barCodeBitmap);
//二维码生成
Bitmap qrCodeBitmap = null;
try {
qrCodeBitmap = QRCodeUtil.createQRCode(dimensionCode, (int) qrCodeWidth);
} catch (Exception e) {
}
qrcodeImg.setImageBitmap(qrCodeBitmap);
}
}
if(!timerIsStart) {
timer.start();
}
}
@Override
public void onError(Throwable e) {
int code = 0;
try {
code = ((NetException) e).getCode();
} catch (Exception error) {
code = 0;
}
if (code == NetException.TOKEN_ERROR) {
NetExceptionUtils.getInstance().tokenNetLoginOut(e, activity);
} else {
if (e != null && !StringUtlis.isEmpty(e.getMessage())) {
ToastTools.showShort(activity, e.getMessage());
}
if(!timerIsStart) {
timer.start();
}
}
}
@Override
public void onComplete() {
}
});
} else {
}
}
考虑:当前使用了比较傻瓜式的自写轮询机制,就是开始拉取一次二维码数据,然而开始轮询,接口访问到,再次倒计时。简单粗暴的方式,也比较好控制,下面先写一个监听是否在后台执行的方法,然后在考虑相关其他判断
[这个方法是直接copy之前很久写的]
/**
* 程序是否在前台运行
*
* @return
*/
public boolean isAppOnForeground() {
ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
String packageName = getApplicationContext().getPackageName();
List appProcesses = activityManager
.getRunningAppProcesses();
if (appProcesses == null) {
return false;
}
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.processName.equals(packageName)
&& appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
return true;
}
}
return false;
}
写好,之后,更具页面的生成周期,开始写入前后台判断
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
if (!isAppOnForeground()) {
//app 从前台进入后台
isActive = false;
timer.cancel();
Logs.d(TAG, "app 从前台进入后台------");
//全局变量isActive = false 记录当前已经进入后台
}
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Logs.d(TAG, "onResume()------");
if (!isActive) {
//app 从后台唤醒,进入前台
Logs.d(TAG, "app 从后台唤醒,进入前台------");
isActive = true;
if (timeStamp > 0) {
long lastTime = System.currentTimeMillis();
if (lastTime - timeStamp > 60 * 1000) {
if(!timerIsStart) {
getNetData();
}
} else {
if(!timerIsStart) {
timer.start();
}
}
} else {
if(!timerIsStart) {
getNetData();
}
}
}
}
哈哈,前后台监控拉取数据就完成了。
本来以为有上面的操作就ojbk了,然而还需要屏蔽掉在当前页面打开一个activity,并且当前页面没有关闭的情况,定时器一直走,下面是生命周期,屏蔽掉了一些比如oncreate()呀,这样对我没什么卵用的
打开当前activity
onPause() ———> onStop() ———-> onResume()
当前activity在打开一个activity 当前activity为
onPause() ————–> onStop()
关闭打开的activiy回到当前activity 生命周期为:
onRestart() ————–> onResume()
顾决定在onRestart()中添加是否第一个页面是当前activiy并加上开启定时器的判断,
在onStop()中添加是否第一个页面是当前activiy的判断,并关闭定时器
于是有了下面的代码:
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Logs.e(TAG,"onResume()------");
if(AppManager.getAppManager().currentActivity()!=null && AppManager.getAppManager().currentActivity() instanceof ScabDiscountFragmentActivity){
Logs.d(TAG, "onResume()当前activity 在栈顶------");
if (!isAppOnForeground()) {
//app 从后台唤醒,进入前台
Logs.d(TAG, "app 从后台唤醒,进入前台------");
isActive = true;
if (timeStamp > 0) {
long lastTime = System.currentTimeMillis();
if (lastTime - timeStamp > 60 * 1000) {
if(!timerIsStart) {
Logs.d(TAG, "onResume()当前activity timeStamp>60*1000 getNetData(); -------");
getNetData();
}else{
Logs.d(TAG, "onResume()当前activity timerIsStart is true -------");
}
} else {
if(!timerIsStart) {
timer.start();
Logs.d(TAG, "onResume()当前activity timeStamp>0 && timeStamp <60*1000 不执行操作 -------");
}
}
} else {
if(!timerIsStart) {
Logs.d(TAG, "onResume()当前activity timeStamp==0 timer关闭执行拉取数据------");
getNetData();
}else{
Logs.d(TAG, "onResume()当前activity timeStamp==0 不执行操作 -------");
}
}
}else{
//在前台操作
if(!timerIsStart) {
Logs.d(TAG, "onResume()当前activity timeStamp==0 timer关闭执行拉取数据------");
getNetData();
}else{
Logs.d(TAG, "onResume()当前activity timeStamp==0 不执行操作 -------");
}
}
}else{
Logs.e(TAG,"onResume()非当前activity---");
if(timerIsStart){
Logs.d(TAG, "onResume()非当前activity timer开启执行关闭------");
timerIsStart=false;
timer.cancel();
}else{
Logs.d(TAG, "onResume()非当前activity timer关闭不开启------");
}
}
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Logs.e(TAG,"onStop()------------->");
if(AppManager.getAppManager().currentActivity()!=null && AppManager.getAppManager().currentActivity() instanceof ScabDiscountFragmentActivity){
//判断当前
if (!isAppOnForeground()) {
//app 从前台进入后台
if(isActive) {
isActive = false;
timerIsStart=false;
timer.cancel();
}
Logs.d(TAG, "app 从前台进入后台------");
//全局变量isActive = false 记录当前已经进入后台
}
}else{
Logs.d(TAG, "当前activity非定栈顶activity------");
if(timerIsStart) {
timerIsStart = false;
timer.cancel();
}
}
}
呵呵,搞定,写好了,开心,商业APP简单粗暴挺好,写一个轮询继麻烦又很消耗性能。简单粗暴ojbk