0

Initially i set myself a simple task to make a function to execute with delay. At first i made a runnable and executed it with new Thread(runnable).start();, but i've read, that non-static inner classes can lead to memory leaks, so i tried to make Runnable as static.

I followed example in Is this Runnable safe from memory leak? and ended with this code:

public class ApproxManager {
    private Context mContext;
    private AlarmManager mAlarmManager;

    public ApproxManager(Context context){
        mContext = context;
        mAlarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    }

    public void setPeriod(int type, long when, int extendCount){
        Intent i = new Intent(mContext, OnAlarmReceiver.class);
        long alarmtime = when;
        i.putExtra(RReminder.PERIOD_TYPE, type);
        i.putExtra(RReminder.EXTEND_COUNT, extendCount);
        i.setAction(RReminder.CUSTOM_INTENT_APPROXIMATE_PERIOD_END);
        PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
        new Thread(new WeakRunnable(mContext, alarmtime,pi)).start();
    }

    public void setAlarm(long alarmTime, PendingIntent pi){
        mAlarmManager.set(AlarmManager.RTC_WAKEUP, alarmTime, pi);
    }

    private static final class WeakRunnable implements Runnable {
        private final WeakReference<Context> mContext;
        long mAlarmtime;
        PendingIntent mpi;

        protected WeakRunnable(Context context, long alarmtime, PendingIntent pi){
        mContext = new WeakReference<Context>(context);
        mAlarmtime = alarmtime;
        mpi = pi;

        }

        @Override
        public void run() {
            Context context = mContext.get();
            if (context != null) {
                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                ApproxManager approxManager = new ApproxManager(context);
                approxManager.setAlarm(mAlarmtime,mpi);
            }
        }
    }
} 

I am unfamiliar with inner classes and referencing, so despite my code appears to be working, i am not sure, if i have suceeded with my goal to avoid memory leaks. So i would appreciate if someone could look at my code.

Community
  • 1
  • 1
aphelion
  • 561
  • 1
  • 5
  • 12
  • 1
    Not really solution but you can greatly reduce memory leakage if you use AplicationContext instead of activity- that way even if leakage happen it won`t hold visual resources in the memory – X3Btel Aug 11 '16 at 15:03
  • Ahh, i see. So, if use ApplicationContext to instantiate my ApproxManager class, my parent activity will be garbage collected even if ApproxManager outlives the activity? – aphelion Aug 11 '16 at 20:01
  • Yes if you use AplicationContext, ApproxManager won`t hold reference to the activity – X3Btel Aug 16 '16 at 07:47

1 Answers1

2

Your code looks fine IMHO. I think you have managed to successfully implement you runnable and protect yourself against a memory leak.

Non - static inner classes hold a implicit reference to the instance that created them. This means that, if you go with the non - static approach, you will be keeping a reference to a ApproxManager instance and this instance will not be garbage collected. The ApproxManager keeps a reference to the Context and AlarmManager instances and they won't be garbage collected neither and this is you memory leak.

Static inner classes don't hold any implicit references, but they can't access non - static members, so you are forced to provide all the needed dependencies so the class can do it's work. Using WeakReference you won't prevent eventual garbage collection of the variable, if there is need for one.

Danail Alexiev
  • 7,624
  • 3
  • 20
  • 28