从窗口小部件中的onDeleted方法调用handler.removeCallbacks会抛出nullpointerexception

时间:2014-12-30 17:55:15

标签: java android nullpointerexception android-widget android-handler

我需要在用户删除窗口小部件时停止处理程序,但调用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);
  }
}

1 个答案:

答案 0 :(得分:0)

问题在于,您不能每次都依赖于Android调用的小部件的相同实例,因此在小部件提供程序中保留非静态字段是一个问题。

一个简单的解决方案是将静态字段用于处理程序和runnable。看起来其他一些字段也可能消失,例如每次调用onProgressUpdate时都会构造PieGraph,因此它可能是本地的。基本上,您应该避免窗口小部件中的所有非静态字段。