ええと...あなたはこれをするべきではありません。
匿名クラスが親クラスのメソッドまたはフィールドにアクセスする方法は、親クラスへの非表示の参照を格納することによるためです。
たとえば、あなたは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.
}
}
コンパイラは実際には次のようなものを生成します。
private static class AnonymousRunnable {
private MyActivity parent;
public AnonymousRunnable(MyActivity parent) {
this.parent = parent;
}
@Override
public void run() {
while (true)
parent.someFunction();
}
}
そのため、親Activity
が(たとえば、構成の変更のために)破棄し、匿名クラスがまだ存在している場合、アクティビティ全体をgc-edすることはできません。(誰かがまだ参照を保持しているためです。)
これがメモリリークになり、アプリをリンボにします!!!
私の場合、次のようなローダー用に「onProgressUpdate()」を実装します。
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));
}
}
そしてあなたのActivity
クラスで
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();
}
}
deleteObserver()
中に覚えておくことonDestroy()
が重要です。このように、ローダーはあなたのアクティビティへの参照を永久に保持しません。(ローダーはおそらくあなたのApplication
ライフサイクルの間生きたままになります...)