2013-08-24 2 views
0

Привет всем,Android Thread Allocation - растущая куча?

Я разрабатываю приложение для Android против API 7 в тот момент, когда я использую действие, которое необходимо перезапустить. Допустим, моя деятельность выглядит следующим образом:

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

Проблема заключается в том, что дс не кажется, чтобы освободить нить fullAnim так что куча растет ~ 100К при каждом запуске - пока она замедляется и падает. Объявление fullAnim как static решает эту проблему, но поскольку я использую нестатические ссылки, это не работает для меня.

Итак, на данный момент я добрался до утра - и я надеюсь, что вы можете посоветовать мне, куда идти дальше. Есть ли что-то, что я могу сделать неправильно или есть инструмент, который я могу использовать для управления потоками, чтобы удалить и освободить кучу после перезагрузки.

любезно касается

UPDATE

спасибо всем, кто ответил - помог много. используя таймер в конце концов. я сделал следующие изменения:

/****** 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();} 
    } 
}; 

как активность была более 6k LOC долго это было довольно приличным решением, не сталкиваясь большими последствиями. KUDOS!

я не использую таймер ГРАФИК задачи - не знаю, если его плохая практика, но анимация называется так:

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

ответ

1

Поскольку конечная переменная имеет низкий приоритет для GC. Таким образом, вам нужно явно освободить объекты-подпрограммы в методе onPause(), потому что не существует функция onDestory(), которая вызовет немедленный вызов после завершения().

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

     System.gc(); 
    } 

UPDATE

использовать таймер для достижения этой цели

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); 
+0

Я пробовал это с помощью написанного примера активности - куча все еще растет:/ – user1386375

+1

Еще одна альтернатива, которую вы можете использовать, - Timer и TimerTask. вы можете отменить таймер при уничтожении. –

+0

thx alot! TimerTask сделал мой день! <3 – user1386375

2

Как и с любой виртуальной машиной Java, память кучи будет автоматически расти до максимальный размер. Но растровые изображения выделяются вне виртуальной машины, поэтому вы не видите их легко в статистике. Самое лучшее, что вы можете сделать, это убедиться, что вы не используете большие растровые изображения, или масштабировать их вниз, используя http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html

От Затмения вы можете создать дамп кучи, когда вы находитесь на Android 1.6 или выше, и вы можете проанализировать дамп с Eclipse MAT.

Как правило, вы не можете контролировать максимальный размер кучи на реальном устройстве, если только вы не работаете с настраиваемым оборудованием или прошивкой.

Должна быть статья на developer.android.com по сбросу кучи на 1.6, но я не могу ее найти. :(

Редактировать Кроме того, я должен упомянуть, что вы можете запросить больше памяти для приложений с помощью

android:largeHeap="true" 

в манифесте. Но это очень плохо, поскольку большинство посоветовало приложение не нуждается в этом.

+0

Я читал, что использование больших растровых изображений может привести к проблемам с распределением, но даже если я не выделяю ЛЮБЫЕ растровые изображения внутри потока/runnables .. для этого примера - fullAnim может быть полностью пустым без ничего в нем - куча все равно будет расти – user1386375

3
  • Работающий Thread никогда мусора.
  • Нить не останавливается автоматически, если ваш Activity останавливается или уничтожается. Это может продолжаться вечно.
  • Каждый нестатический внутренний класс сохраняет ссылку на прилагаемый экземпляр. Например. hand.post(anim1); работает внутри этого внутреннего класса, потому что имеет скрытую ссылку на AllocActivity.this.

Так что вы эффективно сделать, это сохранить ссылку на ваш Activity жив дольше, чем она должна быть живой, то есть до тех пор, после onDestroy.

Обязательно укажите stop threads, если вы не хотите их больше.

1

What happens when all activities of an application finishes?

«Когда вы вызываете отделку() это не означает, что экземпляр Активность мусора. Вы хотите сказать Android вы хотите, чтобы закрыть активность (не показывать больше) . Он все равно будет присутствовать до тех пор, пока Android не решит убить процесс (и, таким образом, завершить DVM), или экземпляр собран из мусора ».

Вы должны реализовать свой собственный метод остановки, чтобы остановить текущую нить, можно сделать вызов к нему в OnDestroy

передать этот Stopping a runnable

В качестве альтернативы вы можете выполнить операцию в AsyncTask и использовать onProgressUpdate() для публикации прогресса в потоке пользовательского интерфейса и использовать cancel (true) в сочетании с проверкой doInBackground(), был ли отменен вызов для остановки задачи.

Смежные вопросы