这是我编写的一个示例应用程序,用于重现我遇到的与内存泄漏相关的问题:
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
没有内存泄漏,线程成功退出。当然state = t.getState();在这种情况下不起作用,应予以评论。
有人解释为什么会这样吗?
答案 0 :(得分:0)
关注您的直接关注,runOnUiThread()
需要Runnable
。虽然Thread
确实实施了Runnable
,但runOnUiThread()
不会将其视为Thread
。请将Runnable
传递给runOnUiThread()
。
其次,永远不要从runOnUiThread()
致电doInBackground()
。只需执行Runnable
或onPreExecute()
中onPostExecute()
的工作,这些工作在主应用程序主题上执行。
第三,如果您曾写过真正的Thread
,请不要在其中忙碌。