Вот пример приложения, которое я написал для воспроизведения проблемы утечки памяти, с которой я столкнулся:
package a.b.mapleak;
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MapLeak extends Activity
{
TextView callVoidText, getNewDataText, getDataStringText;
Button callVoidButton, getNewDataButton, getDataStringButton;
Handler callbackHandler;
MemoryLeak memleak;
private LoadAccountsTask mLoadAccountsTask = null;
private class LoadAccountsTask extends AsyncTask<Void, Void, Object[]> {
private int mCursor1;
private int mCursor2;
private Context context;
private UITask t = new UITask();
@Override
protected Object[] doInBackground(Void... params) {
runOnUiThread(t);
// Create the summaries cursor
mCursor1 = 1;
mCursor2 = 2;
return new Object[] { mCursor1, mCursor2};
};
private class UITask extends Thread {
@Override
public void run() {
int i = 2;
while (i>0) {
i--;
}
Thread.State state=t.getState();
Log.e(ALARM_SERVICE, "Thread state in run is " + state.toString());
}
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getDataStringText = (TextView) findViewById(R.id.getDataString_text);
getDataStringButton = (Button) findViewById(R.id.getDataString_button);
getDataStringButton.setOnClickListener(new Button.OnClickListener() {
long i = 0;
public void onClick(View v) {
if (mLoadAccountsTask != null) mLoadAccountsTask.cancel(true);
mLoadAccountsTask = (LoadAccountsTask) new LoadAccountsTask(this).execute();
}
});
}
}
Я обнаружил, что поток, начатый в runOnUiThread
, никогда не завершался. По какой-то неизвестной мне причине задача была запущена, но вывод
Log.e(ALARM_SERVICE, "Thread state in run is " + state.toString());
каждый раз, когда было указано "Состояние потока в состоянии выполнения НОВОЕ", например '' Тема создана, но никогда не запускалась. '' Таким образом, поток работал непрерывно, предотвращая сборку мусора классом «LoadAccountsTask». Таким образом, в этом примере каждый раз, когда нажимается кнопка - в памяти появляется новый «LoadAccountsTask».
Но, если заменить
private class UITask extends Thread
с
private class UITask implements Run
утечки памяти не было, поток успешно завершен. Конечно, состояние = t.getState (); не будет работать в этом случае и должен быть прокомментирован.
У кого-нибудь есть объяснение, почему это так?