Reputation: 15986
Inside of the handler after I first enter the app from a clean state, the Handler handles the MSG_PULLED action however, the reference to main is null. The weak reference is not null. How can this possibly be happening?
Inspired by this post: This Handler class should be static or leaks might occur: IncomingHandler
static class MainHandler extends Handler {
private final WeakReference<MainActivity> wMain;
static int angle=0;
public MainHandler(MainActivity main) {
super();
this.wMain = new WeakReference<MainActivity>(main);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MainActivity main = wMain.get();
int what = msg.what;
if(what == MSG_PULLED) {
main.startAnim();
}
}
}
And how I initiate the handler:
static MainHandler mainHandler;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainHandler = new MainHandler(this);
mainHandler.sendEmptyMessageDelayed(MSG_PULLED,500);
}
Upvotes: 0
Views: 1428
Reputation: 63955
The Activity
instances in your app are regularly destroyed and new ones are created for example when rotating the display.
Now what should happen in that case is that the old instance is garbage collected and only the new one exists. If you keep the old one around you have created a leak.
Since Handler
are not garbage collectable until they have no more messages (?) they can live longer than the Activity
in witch they were created, which usually leads to leaking the old Activity
(until the Handler
can be collected) since Handler
usually have a strong reference to their Activity
.
The WeakReference
way in your code get's rid of that problem by keeping just a weak link to the Activity
that does not prevent garbage collection.
The problem is that you use the get()
method the wrong way: get()
will only return the original object while it exists. When it's gone you get null
. Here: the Activity
will exists while it is still the active one (determined by the system).
The null
is also not a big problem: when you get null
your Activity
instance is no longer alive (maybe a new one was created, maybe it's completely gone) so you can't do anything useful with it anymore. Animation would not show even if you had still a reference.
Basically do it like below and your problem is solved
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MainActivity main = wMain.get();
// message arrived after activity death
if (main == null) return;
int what = msg.what;
if(what == MSG_PULLED) {
main.startAnim();
}
}
The WeakReference
itself (wMain
) is not null because it is itself strongly references as a member variable. Just the content inside it can / will be null
at some point.
Upvotes: 1