Skip navigation

Tag Archives: android

As every Android apps developer should know, an ANR is thrown by the system when the UI thread of your application fails to update itself for 5 seconds; it follows then that long or recurrent tasks should be executed on separate threads, so as to leave the UI thread free to update itself.  This much is simple enough.  Where things can get a bit tricky is when you have a recurrent task that needs to send messages to the UI thread, perhaps like this:

public class MyActivity extends Activity{

        public final int MSG_UPDATE_INFO = 0;

        private CustomHandler mvMainThreadHandler;

        @Override

        protected void onCreate(Bundle savedInstanceState){

        super.onCreate(savedInstanceState);

        mvMainThreadHandler = new CustomHandler(this,Looper.getMainLooper());

        MyRunnable runner = new MyRunnable();

        Thread myThread = new Thread(runner);

        myThread.start();

        }

        private class MyRunnable implements Runnable{
        private boolean bIsUpdating = true;

        public boolean getIsUpdating(){

        return bIsUpdating;

        }

        public void setIsUpdating(boolean b){

        bIsUpdating = b;

        }

        @Override

        public void run(){

        while(bIsUpdating){

        //do something while updating is true

        //send message to main thread to let it know

//something has been done

        mvMainThreadHandler.sendMessage(

mvMainThreadHandler.obtainMessage(MSG_UPDATE_INFO));

        }

        }
        }

        private static class CustomHandler extends Handler{
                
                private WeakReference<MyActivity> whAct;
                
                public CustomHandler(MyActivity act,Looper mainLooper){
                    super(mainLooper);
                    
                    whAct = new WeakReference<MyActivity>(act);
                    
                }

                @Override
                public void handleMessage(Message msg){
                    MyActivity hAct = whAct.get();
                    if(hAct != null){
                        
                        if(msg.what == hAct.MSG_UPDATE_INFO){
                          //stuff
                            
                        }
            
                    }//End if hAct != null
                    else{
                        Log.e(TAG, "hAct, derived from whAct.get(), is null");
                    }
                }
                
            }

        }

This is almost fine… except that the run() method of MyRunnable will send the MSG_UPDATE_INFO message to the UI thread on every CPU clock cycle (or as near to that as it can), which will congest the UI thread and stop it from updating itself possibly for long enough to cause an ANR.  The solution is simple– re-implement MyRunnable::run() like so:

@Override

public void run(){

while(bIsUpdating){

try{

Thread.sleep(1000);

}catch (InterruptedException e) {
                    
       e.printStackTrace();

}

//do something while updating is true

//send message to main thread to let it know

//something has been done

mvMainThreadHandler.sendMessage(mvMainThreadHandler.obtainMessage(MSG_UPDATE_INFO));

}

 

with that small but imperative change the info update thread cannot send messages to the UI thread more frequently than once per 1 second, which should clear up the UI thread’s execution pipeline sufficiently to prevent ANRs.  Note though that the 1 second sleep time was chosen arbitrarily and depending on your recurrent task, your target platform, and the rest of your app, it may need to be a specific value; that said, it worked for me!Image