我需要在用户删除窗口小部件时停止处理程序,但调用handler.removeCallbacks会从onDeleted方法抛出nullpointerexception。我尝试了其他解决方法,比如在实现runnable的类中创建一个方法来杀死runnable,但这也会引发nullpointerexception。
也许在调用onDeleted方法之后,handler会变为null,所以我试着将它放在onDisabled方法中,但没有任何停止。
我做错了什么?
这里是代码:
public class RAMWidget extends AppWidgetProvider {
private PieGraph pg;
private Context context;
private RemoteViews remoteViews;
private AppWidgetManager appWidgetManager;
private ComponentName widget;
private Handler handler;
private CustomRunnable runnable;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
this.context=context;
this.appWidgetManager=appWidgetManager;
remoteViews=new RemoteViews(context.getPackageName(),R.layout.widget_ram);
widget=new ComponentName(context,RAMWidget.class);
new DrawTask().execute();
handler=new Handler();
runnable=new CustomRunnable();
handler.postDelayed(runnable,3000);
}
private class CustomRunnable implements Runnable
{
private boolean stop;
public CustomRunnable()
{
stop=false;
}
@Override
public void run()
{
new DrawTask().execute();
Log.i("STOP",stop+"");
if(!stop)
handler.postDelayed(this,3000);
else
return;
Log.i("STOP",stop+"");
}
void killThread()
{
stop=true;
}
}
private class DrawTask extends AsyncTask<Void,Void, Void>
{
private PieSlice slice,_slice;
private long total=0,free=0,rate=0;
@Override
protected Void doInBackground(Void... unused)
{
RandomAccessFile reader=null;
try
{
reader=new RandomAccessFile("/proc/meminfo","r");
long[] mems=new long[4];
for(int i=0;i<4;i++)
{
String load = reader.readLine();
String[] toks = load.split(":");
mems[i] = Long.parseLong(toks[1].replace("kB","").trim());
}
total=mems[0]/1024;
free=(mems[1]+mems[2]+mems[3])/1024;
rate=(int)((float)(total-free)/total*100);
}
catch (Exception e)
{
e.printStackTrace();
}
if(reader!=null)
try
{
reader.close();
}
catch (IOException e)
{
e.printStackTrace();
}
slice=new PieSlice();
slice.setTitle("Available RAM");
slice.setColor(Color.parseColor("#99CC00"));
slice.setValue(total-free);
_slice=new PieSlice();
_slice.setTitle("Used RAM");
_slice.setColor(Color.parseColor("#FFBB33"));
_slice.setValue(free);
publishProgress();
return null;
}
@Override
protected void onProgressUpdate(Void... values)
{
pg=new PieGraph(context);
pg.measure(200,200);
pg.layout(0,0,200,200);
pg.setDrawingCacheEnabled(true);
pg.addSlice(slice);
pg.addSlice(_slice);
pg.setInnerCircleRatio(150);
for (PieSlice s : pg.getSlices())
s.setGoalValue(s.getValue());
pg.setDuration(1000);
pg.setInterpolator(new AccelerateDecelerateInterpolator());
pg.animateToGoalValues();
pg.setPadding(3);
remoteViews.setTextViewText(R.id.widget_ram_text, "Total RAM " + total + " MB");
remoteViews.setTextViewText(R.id.widget_ram_text1,"Avaiable RAM "+(total-free)+" MB");
remoteViews.setTextViewText(R.id.widget_ram_text2,"Used RAM "+free+" MB");
Bitmap bitmap=pg.getDrawingCache();
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);
paint.setTextSize(18);
paint.setShadowLayer(1f,0f,1f,Color.WHITE);
Rect bounds=new Rect();
paint.getTextBounds(rate+" %",0,new String(rate+" %").length(),bounds);
int x=(bitmap.getWidth()-bounds.width())/2;
int y=(bitmap.getHeight()+bounds.height())/2;
canvas.drawText(rate+" %",x,y,paint);
remoteViews.setImageViewBitmap(R.id.graph_widget,bitmap);
appWidgetManager.updateAppWidget(widget,remoteViews);
}
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
runnable.killThread();
handler.removeCallbacks(runnable); //both of them don't work
super.onDeleted(context, appWidgetIds);
}
@Override
public void onDisabled(Context context) {
runnable.killThread();
handler.removeCallbacks(runnable);
super.onDisabled(context);
}
}
答案 0 :(得分:0)
问题在于,您不能每次都依赖于Android调用的小部件的相同实例,因此在小部件提供程序中保留非静态字段是一个问题。
一个简单的解决方案是将静态字段用于处理程序和runnable。看起来其他一些字段也可能消失,例如每次调用onProgressUpdate时都会构造PieGraph,因此它可能是本地的。基本上,您应该避免窗口小部件中的所有非静态字段。