最近公司要编写一个定时刷新的widget,到网上找了下,发现好多人都已经总结出来了,无非都是以下几种方法
第一种:Timer
Timer这种方式最为常见,起个定时刷新的任务,不用的时候cancel掉,置为空即可。
示例代码:
Timer timer = new Timer( );
TimerTask task = new TimerTask( ) {
public void run ( ) {
Message message = new Message( );
message.what = 1;
handler.sendMessage(message);
}
};
final Handler handler = new Handler( ) {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
log.e("Timer","Timer");
update( );
break;
}
第二种:Alarm
示例代码:
开始计时
Intent intent = new Intent(widgetUpdate);
refreshIntent = PendingIntent.getBroadcast(pContext, 0, intent, 0);
alarm = (AlarmManager)pContext.getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC, 0, 1000, refreshIntent);//每秒刷新1次
停止计时
if (alarm!=null) {
alarm.cancel(refreshIntent);
refreshIntent.cancel();
refreshIntent = null;
alarm = null;
}
第三种:handler
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
public void run () {
update();
handler.postDelayed(this,1000);
}
};
开始计时
handler.removeCallbacks(runnable);
handler.postDelayed(runnable,1000);
停止计时
handler.removeCallbacks(runnable);
当时我也没多想,拷过去直接使用,但是测试了才知道,真正用了这几种方法去更新都会导致launcher有卡壳的现象,而且更新时在执行appWidgetManager.updateAppWidget(thisWidget, rv);这条语句是会随着时间的增加,执行的时间也增加。由开始的几毫秒到几百毫秒。
后来想想这种卡壳会不会是应该更新语句跟launcher在同一线程中的原因呢,按这个思路我启动了一个Service,然后在启动一个线程,让更新语句在这个线程中执行。貌似launcher的滑屏效果还真得到解决了。
以下是service类的源码:
package com.fxun.app.suggest.main;
import java.util.LinkedList;
import java.util.Queue;
import com.fxun.app.suggest.R;
import com.fxun.app.suggest.widget.FxunAppWidgetProvider;
import com.fxun.app.suggest.widget.FxunApplication;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import android.text.format.Time;
import android.widget.RemoteViews;
public class UpdateService extends Service implements Runnable {
private static boolean sThreadRunning = false;
private static Object sLock = new Object();
public static final String ALARM_UPDATA_ACTION = "com.fxun.app.suggest.action.APPWIDGET_ALARM_UPDATE";
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
MLog.d(this, "onStart startId = " + startId);
synchronized (sLock) {
if (!sThreadRunning) {
sThreadRunning = true;
new Thread(this).start();
}
}
}
@Override
public void run() {
updataMiddleLayout();
startAlarmFlash();
}
/**
* 启动一个定时器,定时器只启动一次,下次启动服务时有会再次启动,从而实现循环,所以只用了am.set()做处理
*/
public void startAlarmFlash() {
FxunApplication fxunApplication = (FxunApplication) this
.getApplicationContext();
if (fxunApplication.mPageInfos != null
&& fxunApplication.mPageInfos.size() > 0) {
long flashTime = 0;
if (fxunApplication.mPageInfos.get(0).flashTime != null) {
flashTime = Long
.parseLong(fxunApplication.mPageInfos.get(0).flashTime);
}
MLog.d(this, "startAlarmFlash start = " + flashTime);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, UpdateService.class);
intent.setAction(ALARM_UPDATA_ACTION);
PendingIntent pi = PendingIntent.getService(this, 1, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
am.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+flashTime, pi);
MLog.d(this, "startAlarmFlash end = " + flashTime);
}
}
/**
* 取消定时器,这个方法可以在provide里面的onDisabled里面执行
* @param context
*/
public static void cancelAlarm(Context context){
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, UpdateService.class);
intent.setAction(ALARM_UPDATA_ACTION);
PendingIntent pi = PendingIntent.getService(context, 1, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
am.cancel(pi);
pi.cancel();
pi=null;
}
/*
* 此方法是widget界面更新
*/
public void updataMiddleLayout() {
FxunApplication fxunApplication = (FxunApplication) this
.getApplicationContext();
if (fxunApplication.mPageInfos != null
&& fxunApplication.mPageInfos.size() > 0) {
if ((++fxunApplication.pageInfoIndex) >= fxunApplication.mPageInfos
.size()) {
fxunApplication.pageInfoIndex = 0;
}
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
PageInfo pageInfo=fxunApplication.mPageInfos.get(fxunApplication.pageInfoIndex);
MLog.d(this, "updataMiddleLayout pageInfo=" + pageInfo);
long t = System.currentTimeMillis();
// MLog.d(this,
// "updataMiddleLayout pageInfo.bannerBitmapUri="+pageInfo.bannerBitmapUri);
RemoteViews rv = new RemoteViews(getPackageName(),
R.layout.widget_layout);
rv.setImageViewUri(R.id.banner, pageInfo.bannerBitmapUri);
Intent intent = new Intent();
intent.setClassName(FxunAppWidgetProvider.appApkPackage,
FxunAppWidgetProvider.appApkClass);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);// 只启动一个
Bundle extras = new Bundle();
extras.putString("action", pageInfo.bannerParam);
intent.putExtras(extras);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.banner, pendingIntent);
int id = R.id.app_1_icon;
int count = pageInfo.itemInfos.size();
IconInfo iconInfo;
for (int i = 0; i < count; i++) {
iconInfo = pageInfo.itemInfos.get(i);
intent.setClassName(FxunAppWidgetProvider.appApkPackage,
FxunAppWidgetProvider.appApkClass);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);// 只启动一个
extras = new Bundle();
extras.putString("action", iconInfo.paramString);
intent.putExtras(extras);
pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(id, pendingIntent);
// MLog.d(this,
// "updataMiddleLayout iconInfo.iconBitmaUri="+iconInfo.iconBitmaUri);
rv.setImageViewUri(id++, iconInfo.iconBitmaUri);
// MLog.d(this,
// "updataMiddleLayout iconInfo.titleString="+iconInfo.titleString);
rv.setTextViewText(id++, iconInfo.titleString);
}
MLog.d(this,
"updataMiddleLayout time0="
+ (System.currentTimeMillis() - t));
MLog.d(this,
"updataMiddleLayout time1="
+ (System.currentTimeMillis() - t) );
appWidgetManager.updateAppWidget(new ComponentName(
this, FxunAppWidgetProvider.class), rv);
MLog.d(this,
"updataMiddleLayout time2="
+ (System.currentTimeMillis() - t));
sThreadRunning = false;
}
}
}