静态内部类访问外部类元素

时间:2016-03-13 13:06:34

标签: android memory

这是我的代码,我想把我的内部类静态化以避免内存泄漏。

让我解释一下......我已经制作了一个带有runnable和处理程序的计时器。但是,当我检查android studio中的内存使用情况时,我会看到内存正在上升,然后上升。

我认为我的实施有问题,但我不知道它是什么。

我的研究导致我用runnable创建一个静态类,但是当我这样做时,我无法访问外部classe变量或振动器服务。

public class ActiviteCompteARebours extends AdMobActivity {

private       int       compteurTimer,
                        int_rowTime_display,
                        int_total_time_in_millis;
private       boolean   doubleBackExit;
private       boolean   bln_addTime              = false;
private       int       pressed                  = 0;
private final int       PERCENT                  = 120000;
private final int       INT_MILLIS               = 1000;
private final int       INTERVALLE               = 100;
private final int       AJOUTE_30_SEC            = 30000;
private final String    str_compteurEntrainement = "compteurEntrainement";

private Handler         handler;
private TimerRunnable   runnable;
private Button          btn_passer;
private TextView        txt_countDown;
private ProgressBar     progressBar;

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

    progressBar   = (ProgressBar)   findViewById(R.id.progressBar);
    btn_passer    = (Button)        findViewById(R.id.btn_entrainement);
    txt_countDown = (TextView)      findViewById(R.id.txtView_countDown);

    int_total_time_in_millis = PERCENT;         //Temps total en mili secondes
    int_rowTime_display      = PERCENT;         //Temps total pour l'affichage
    runnable                 = new TimerRunnable();
    handler                  = new Handler();


    progressBar.setMax     (PERCENT);           //Valeur max de la progress bar = 2 minutes (120000 ms)
    progressBar.setProgress(PERCENT);           //Fixe la valeur de la progresse bar a 2 minutes

    Intent intent = getIntent();
    compteurTimer = intent.getExtras().getInt(str_compteurEntrainement,1); //


    txt_countDown.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            runnable.addTime();                                  //on stop le timer
            handler.removeCallbacksAndMessages(runnable);        //on annule les message du handler
            int_total_time_in_millis =
                    runnable.getTimeInMillis() + AJOUTE_30_SEC ; //recupere le temps et ajoute 30 sec
            bln_addTime              = false;                    //sinon le timer ne se lance pas
            int_rowTime_display      = int_total_time_in_millis; //pour l'affiche du nouveau temps

            progressBar.setMax(int_total_time_in_millis);        //fixe le max
            progressBar.setProgress (int_total_time_in_millis);  //fixe la valeur de la progressBar

            handler.postDelayed(runnable,INTERVALLE);             //relance le timer
        }
    });


    btn_passer.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {                    //Action lors du click sur le boutton "passer"
            if(runnable != null){
                runnable.killRunnable();                        //Retour à l'activite precedente
            }
           }
    });

    //Run Timer
    //call handler post delayed to resume the runnable
    handler.postDelayed(runnable, 100);
}//onCreate

  private class TimerRunnable implements Runnable{

private final Vibrator vibreur             = (Vibrator) getSystemService(VIBRATOR_SERVICE);     //service de vibration
private final int      INT_SEC             = 60;
private       boolean  isCanceled          = false;
private       int      int_progress_value;

@Override
public void run() {
    //if time is added
    if (bln_addTime){
        runnable = null;

    }//if the timer is canceled or the total time = the progress time
    else if(isCanceled || int_total_time_in_millis == int_progress_value){
        //set runnable to null
        runnable = null;

        vibreur.vibrate(200);
        workoutIntent();

        //return
        return;
    }
    else{

        //increment int_progess_value
        int_progress_value += INTERVALLE;

        //update the time in the screen for the countdown
        int_rowTime_display -= INTERVALLE;

        progressBar.setSecondaryProgress(int_progress_value);

        //get the time in seconds by dividing by 1000
        int row_min = int_rowTime_display / INT_MILLIS;
        String time = ""+ row_min / INT_SEC + ":";
        String sec = ""+row_min % INT_SEC;

        if(row_min % INT_SEC < 10){
            time += "0" + sec;
        }else{
            time += sec;
        }
        //divide row_min by 60 to get minutes. and row_min % 60 to get seconds
        txt_countDown.setText(time);

        //controle le temps pour vibrer lors des 3 dernières secondes
        //on utilise l'incrémentation de la progressbar pour être plus précis
        //on prends 1 sentième avant pour anticiper le postDelayed de une seconde
        /*if (int_progress_value == int_total_time_in_millis-1110 ||
                int_progress_value == int_total_time_in_millis-2110 ||
                int_progress_value == int_total_time_in_millis-3110){
          */
        if(int_rowTime_display == 300 || int_rowTime_display == 200){vibreur.vibrate(100);}

        /* show add 5 seconds after countDown start */
        if ((compteurTimer == 2 || compteurTimer == 4) && int_progress_value == 5000){
            showInterstitial();  //adMob 
        }
    }

    handler.postDelayed(this,INTERVALLE);
}//run

public void killRunnable(){
    //when timer is paused or stopped isCanceled is set to true.
    isCanceled = true;
}

public int getTimeInMillis(){
    return int_rowTime_display;
}

public void addTime(){
    //when timer is paused or stopped isCanceled is set to true.
    bln_addTime = true;
}
}//Runnable

void workoutIntent() {
    //création d'un nouvel intent vers l'entraînement
    Intent workout = new Intent(ActiviteCompteARebours.this, ActiviteEntrainement.class);

    //on augmente le compteur ce qui permettra de passer à la série suivante sur l'intent entrainement
    compteurTimer++;

    //ajout de l'extra pour l'intent entrainement
    workout.putExtra(str_compteurEntrainement, compteurTimer);
    //on cherche si une activité workout existe et on la ramène en première position
    workout.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    //Comme l'activité ActiviteEntrainement attend un résultat on retourne le résultat OK
    setResult(RESULT_OK, workout);

    // fin de l'activité ActiviteCompteARebours
    finish();
}

protected void onDestroy() {
    super.onDestroy();
    Log.d("TIMER", "Arrêt du timer, onDestroy Method");
    if(runnable != null){
        runnable.killRunnable();
        handler.removeCallbacks(runnable);
        runnable = null;
    }
}

`

1 个答案:

答案 0 :(得分:0)

仅仅因为内部类在外部类中被编写,它无法访问其变量或方法。这是因为它没有引用外部类的对象

自由访问并发运行的线程的变量也会造成严重的正确性问题,因为在线程B尝试修改其变量的时间点,没有人能够知道线程A将处于哪个状态。正确的方法是使用AsyncTask,如https://developer.android.com/guide/components/processes-and-threads.html中所述,其中doInBackground方法用于将信息从调用线程传递到新线程,onPostExecute携带信息回到来电者。