I've converted my AsyncTask
to an AsyncTaskLoader
(mostly to deal with configuration changes). I have a TextView
I am using as a progress status and was using onProgressUpdate
in the AsyncTask
to update it. It doesn't look like AsyncTaskLoader
has an equivalent, so during loadInBackground
(in the AsyncTaskLoader
) I'm using this:
getActivity().runOnUiThread(new Runnable() {
public void run() {
((TextView)getActivity().findViewById(R.id.status)).setText("Updating...");
}
});
I am using this in a Fragment
, which is why I'm using getActivity()
. This work pretty well, except when a configuration change happens, like changing the screen orientation. My AsyncTaskLoader
keeps running (which is why I'm using an AsyncTaskLoader
), but the runOnUiThread
seems to get skipped.
Not sure why it's being skipped or if this is the best way to update the UI from an AsyncTaskLoader
.
UPDATE:
I ended up reverting back to an AsyncTask
as it seems better suited for UI updates. Wish they could merge what works with an AsyncTask
with an AsyncTaskLoader
.
It's actually possible. You essentially need to subclass the AsyncTaskloader
and implement a publishMessage()
method, which will use a Handler
to deliver the progress message to any class that implements the ProgressListener
(or whatever you want to call it) interface.
Download this for an example: http://www.2shared.com/file/VW68yhZ1/SampleTaskProgressDialogFragme.html (message me if it goes offline) - this was based of http://habrahabr.ru/post/131560/
Emm... you shouldn't be doing this.
because how an anonymous class access parent class Method or Field is by storing an invisible reference to the parent class.
for example you have a Activity
:
public class MyActivity
extends Activity
{
public void someFunction() { /* do some work over here */ }
public void someOtherFunction() {
Runnable r = new Runnable() {
@Override
public void run() {
while (true)
someFunction();
}
};
new Thread(r).start(); // use it, for example here just make a thread to run it.
}
}
the compiler will actually generate something like this:
private static class AnonymousRunnable {
private MyActivity parent;
public AnonymousRunnable(MyActivity parent) {
this.parent = parent;
}
@Override
public void run() {
while (true)
parent.someFunction();
}
}
So, when your parent Activity
destroys (due to configuration change, for example), and your anonymous class still exists, the whole activity cannot be gc-ed. (because someone still hold a reference.)
THAT BECOMES A MEMORY LEAK AND MAKE YOUR APP GO LIMBO!!!
If it was me, I would implement the "onProgressUpdate()" for loaders like this:
public class MyLoader extends AsyncTaskLoader<Something> {
private Observable mObservable = new Observable();
synchronized void addObserver(Observer observer) {
mObservable.addObserver(observer);
}
synchronized void deleteObserver(Observer observer) {
mObservable.deleteObserver(observer);
}
@Override
public void loadInBackground(CancellationSignal signal)
{
for (int i = 0;i < 100;++i)
mObservable.notifyObservers(new Integer(i));
}
}
And in your Activity
class
public class MyActivity extends Activity {
private Observer mObserver = new Observer() {
@Override
public void update(Observable observable, Object data) {
final Integer progress = (Integer) data;
mTextView.post(new Runnable() {
mTextView.setText(data.toString()); // update your progress....
});
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreated(savedInstanceState);
MyLoader loader = (MyLoader) getLoaderManager().initLoader(0, null, this);
loader.addObserver(mObserver);
}
@Override
public void onDestroy() {
MyLoader loader = (MyLoader) getLoaderManager().getLoader(0);
if (loader != null)
loader.deleteObserver(mObserver);
super.onDestroy();
}
}
remember to deleteObserver()
during onDestroy()
is important, this way the loader don't hold a reference to your activity forever. (the loader will probably be held alive during your Application
lifecycle...)
Answering my own question, but from what I can tell, AsyncTaskLoader
isn't the best to use if you need to update the UI.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With