26565

Calling handler.removeCallbacks from onDeleted method in a widget throws a nullpointerexception

Question:

I need to stop the handler when the widget is removed by the user but calling handler.removeCallbacks throws a nullpointerexception from the onDeleted method. I tried other workarounds like creating a method,in a class which implements runnable, to kill the runnable but this throw a nullpointerexception also. <br />Maybe handler gets null after the call of the onDeleted method so I tried to put it in the onDisabled method but nothing stop. <br />What am I doing wrong?

Here the code :

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); } }

Answer1:

The problem is that you can't depend on the same instance of your widget being called by Android each time, and so keeping non-static fields in your widget provider is a problem.

An easy solution would be to use static fields for handler and runnable. It looks like some of the other fields could go away too, for example PieGraph is constructed each time onProgressUpdate is called, so it could be a local. Basically you should avoid all non-static fields in a widget.

Recommend

  • How to use CompletableFuture without risking a StackOverflowError?
  • Picasso Taking time to load images
  • How to upload specific List image using click on Upload button
  • How can I tell a form not to dispose a particular control when it closes?
  • SonarQube: Cannot deactivate rule with missing quality profile
  • Update CALayer sublayers immediately
  • JFileChooser in front of fullscreen Swing application
  • Trying to switch camera back to front but getting exception
  • Can a Chrome extension content script make an jQuery AJAX request for an html file that is itself a
  • How to limit post in wp_query
  • Upload files with Ajax and Jquery
  • Build own AppleScript numerical error handling
  • SVN: Merging two branches together
  • Hibernate gives error error as “Access to DialectResolutionInfo cannot be null when 'hibernate.
  • Cannot Parse HTML Data Using Android / JSOUP
  • using conditional logic : check if record exists; if it does, update it, if not, create it
  • AngularJs get employee from factory
  • Proper way to use connect-multiparty with express.js?
  • How to CLICK on IE download dialog box i.e.(Open, Save, Save As…)
  • Java static initializers and reflection
  • Exception on Android 4.0 `android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode)`
  • Change div Background jquery
  • How to stop GridView from loading again when I press back button?
  • Can Visual Studio XAML designer handle font family names with spaces as a resource?
  • IndexOutOfRangeException on multidimensional array despite using GetLength check
  • Bitwise OR returns boolean when one of operands is nil
  • unknown Exception android
  • sending mail using smtp is too slow
  • Is there any way to bind data to data.frame by some index?
  • Django query for large number of relationships
  • Busy indicator not showing up in wpf window [duplicate]
  • costura.fody for a dll that references another dll
  • Why is Django giving me: 'first_name' is an invalid keyword argument for this function?
  • Binding checkboxes to object values in AngularJs
  • Observable and ngFor in Angular 2
  • How can I use `wmic` in a Windows PE script?
  • failed to connect to specific WiFi in android programmatically
  • UserPrincipal.Current returns apppool on IIS
  • java string with new operator and a literal
  • How to push additional view controllers onto NavigationController but keep the TabBar?