user1386375
user1386375

Reputation: 213

Android Thread Allocation - growing heap?

Hi everyone out there,

i am developing an android application against API 7 at the moment in which i use an activity which need to be restarted. Lets say my activity looks like this:

public class AllocActivity extends Activity implements OnClickListener{

    Button but;
    private Handler hand = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_alloc);

        but = (Button) findViewById(R.id.button);
        but.setText("RELOAD");
        but.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0){
                Intent intent = getIntent();
                startActivity(intent);
                finish();
            }
        });  
    }

    @Override
    protected void onDestroy(){
        super.onDestroy();
        System.gc();
    }

    /****** THREADS AND RUNNABLES ******/

    final Runnable fullAnim = new Thread(new Runnable(){
        @Override
        public void run(){
            try{
                hand.post(anim1);
                Thread.sleep(2000);
                hand.post(anim2);
                Thread.sleep(1000);
                // and so on
            }catch(InterruptedException ie){ie.printStackTrace();}
        }
    });

    final Runnable anim1 = new Runnable() {
        @Override
        public void run(){
            // non-static method findViewById
            ImageView sky = (ImageView)findViewById(R.id.sky);
        }
    };
}

The problem is that the gc doesnt seem to free the fullAnim thread so that the heap is growing by ~100K at every restart - till it slows down and crashes. Declaring fullAnim as static does solve this problem - but as i use non static references this doesnt work out for me.

So at this point i am kindof lost - and i hope u can advice me where to go next. Is there something i might be doing wrong or is there a tool i can use to manage threads to drop and free heap after restart.

kindly regards

UPDATE

thanks to everyone who answered - helped alot. using TimerTask did the trick in the end. i did the following change:

/****** THREADS AND RUNNABLES ******/

final TimerTask fullAnim = new TimerTask(){
    @Override
    public void run(){
        try{
            hand.post(anim1);
            Thread.sleep(2000);
            hand.post(anim2);
            Thread.sleep(1000);
            // and so on
        }catch(InterruptedException ie){ie.printStackTrace();}
    }
};

as the activity was more than 6k loc long this was a pretty decent solution without facing bigger impacts. KUDOS!

i dont use a Timer to shedule the task - dont know if its bad practice but the animation is called like this:

Thread t = new Thread(fullAnim);
t.start();

Upvotes: 0

Views: 1189

Answers (3)

Biraj Zalavadia
Biraj Zalavadia

Reputation: 28484

Because final variable have low priority for GC. So you need to explicitly release the runneable objects in onPause() method because there is not ensurence onDestory() will call immediate after finish() call .

@Override
    protected void onPause(){
        super.onPause();
        //cancel timer to stop animations
       if(t!=null){
        t.cancel();
       }

        System.gc();
    }

UPDATE

use timer to achieve this

boolean isFirstAnim=true;
Timer t = new Timer();
        t.schedule(new TimerTask() {

            @Override
            public void run() {
                          if(isFirstAnim){
                              // play your first animation at every
                          }else{
                              // play your second animation at every
                          }                 
            }
        }, 0, 3000);

Upvotes: 1

Sunny Kumar Aditya
Sunny Kumar Aditya

Reputation: 2846

What happens when all activities of an application finishes?

"When you call finish() this doesn't mean the Activity instance is garbage collected. You're telling Android you want to close the Activity (do not show it anymore). It will still be present until Android decides to kill the process (and thus terminate the DVM) or the instance is garbage-collected."

You need to implement your own stop method to stop the running thread, you can make a call to it in onDestroy

refer this Stopping a runnable

Alternatively you can perform your operation in an asynctask and use onProgressUpdate() to publish progress on UI thread and use cancel(true) in combination with check in doInBackground() whether cancel has been called to stop the task.

Upvotes: 1

zapl
zapl

Reputation: 63955

  • A running Thread is never garbage collected.
  • A Thread is not stopped automatically if your Activity stops or is destroyed. It could run forever.
  • Every non-static inner class keeps a reference to the enclosing instance. E.g. hand.post(anim1); works inside that inner class because it has an implicit reference to AllocActivity.this.

So what you effectively do is to keep a reference to your Activity alive for longer than it is supposed to be alive, i.e. until after onDestroy.

Make sure to stop threads manually if you don't want them anymore.

Upvotes: 4

Related Questions