这是我的代码(简化了一点):
服务
public class TaskService extends Service {
// -----------------------------------------------------------------------
//
// Constants
//
// -----------------------------------------------------------------------
private static final String EXTRA_TASK = "EXTRA_TASK";
private static final String TASK_REGISTER_INSTALLATION = "TASK_REGISTER_INSTALLATION";
private static Handler sHandler = new Handler();
// -----------------------------------------------------------------------
//
// Statics
//
// -----------------------------------------------------------------------
public static void registerInstallation(Context context) {
Intent intent = new Intent(context, TaskService.class);
intent.putExtra(EXTRA_TASK, TASK_REGISTER_INSTALLATION);
context.startService(intent);
}
// -----------------------------------------------------------------------
//
// Fields
//
// -----------------------------------------------------------------------
private List<BaseTask> mTasks = new ArrayList<BaseTask>();
// -----------------------------------------------------------------------
//
// Methods
//
// -----------------------------------------------------------------------
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null)
handleIntent(intent);
return Service.START_NOT_STICKY;
}
private void handleIntent(Intent intent) {
String taskType = intent.getStringExtra(EXTRA_TASK);
if (taskType.equalsIgnoreCase(TASK_REGISTER_INSTALLATION)) {
RegistrationTask task = new RegistrationTask("",
"", "", "", "");
task.setTaskListener(sHandler, mRegistrationListener);
mTasks.add(task);
task.start();
}
}
@Override
public void onDestroy() {
for (BaseTask task : mTasks)
task.interrupt();
mTasks.clear();
Log.d(TaskService.class.getSimpleName(), "onDestroy");
super.onDestroy();
}
private TaskListener<String, String, String> mRegistrationListener = new TaskListener<String, String, String>() {
@Override
public void onResult(String result, BaseTask task) {
mTasks.remove(task);
}
@Override
public void onProgress(String progress, BaseTask task) {
mTasks.remove(task);
}
@Override
public void onError(String error, BaseTask task) {
Toast.makeText(TaskService.this, error, Toast.LENGTH_SHORT).show();
}
};
public static interface TaskListener<ResultType, ProgressType, ErrorType> {
public void onError(ErrorType error, BaseTask task);
public void onProgress(ProgressType progress, BaseTask task);
public void onResult(ResultType result, BaseTask task);
}
}
发
public class BaseTask<ResultType, ProgressType, ErrorType> extends Thread {
protected Handler mHandler;
protected TaskListener<ResultType, ProgressType, ErrorType> mTaskListener;
protected HttpRequestFactory mRequestFactory;
public BaseTask() {
try {
ApacheHttpTransport.Builder builder = new ApacheHttpTransport.Builder();
mRequestFactory = builder.doNotValidateCertificate().build()
.createRequestFactory();
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
}
public void setTaskListener(Handler handler,
TaskListener<ResultType, ProgressType, ErrorType> listener) {
mHandler = handler;
mTaskListener = listener;
}
protected void onError(final ErrorType error) {
mHandler.post(new Runnable() {
@Override
public void run() {
mTaskListener.onError(error, BaseTask.this);
}
});
}
protected void onProgress(final ProgressType progress) {
mHandler.post(new Runnable() {
@Override
public void run() {
mTaskListener.onProgress(progress, BaseTask.this);
}
});
}
protected void onResult(final ResultType result) {
mHandler.post(new Runnable() {
@Override
public void run() {
mTaskListener.onResult(result, BaseTask.this);
}
});
}
}
public class RegistrationTask extends BaseTask<String, String, String> {
public RegistrationTask(...) {
super();
}
@Override
public void run() {
try {
//Simple web request executed here
} catch (HttpResponseException e) {
e.printStackTrace();
onError(e.getContent());
} catch (IOException e) {
e.printStackTrace();
}
}
我还有Activity
每次调用Intent
方法发送onCreate
以启动任务。问题是,经过几次重启后,我得到大约300rb泄漏,即使我从Eclipse调用GC,我也没有被释放。我做错了什么?
更新 活动代码:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TaskService.registerInstallation(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
你可以看到它非常简单。
答案 0 :(得分:0)
这个答案不会给你一个明确的解决方案,不是因为我不愿意,而是因为它不可能(甚至更难,不仅仅是查看你的代码,而是非常了解你的代码)。但根据我的经验,我可以告诉你,由于直接引用的对象不会发生那种内存泄漏 - 你声明的对象(并继续引用另一个类/对象)依赖于许多其他类等等,并且可能您看到由于对任何实例的错误处理而导致内存泄漏,同时引用其他实例。
调试内存泄漏通常是一项非常艰苦的工作,不仅仅是因为正如我上面所述,它有时并不直接依赖于您声明的内容,而且因为找到解决方案可能并非易事。您可以做的最好的事情就是您似乎正在做的事情:DDMS + HPROF。我不知道你有多少知识,但是虽然它不是一种通用的方法,this link帮助我找到了代码中的内存泄漏。
虽然看起来微不足道,但调试这类事情的最佳方法是逐步删除代码的一部分(总体而言,意味着使用其他类的实例)并查看HPROF报告的更改方式。
答案 1 :(得分:0)
您的服务不会随着您的活动而破坏。最有可能的是,您在服务中生成的每个线程中保留对Activity的引用,这意味着它不会被销毁。
如果您需要引用您的活动,您应该使用WeakReference:
How to use WeakReference in Java and Android development?
如果这不是问题,那么像我们看不到代码的RegistrationTask这样的对象就是罪魁祸首 - 但听起来你可能已经尝试删除代码位......你总是可以发布更多的代码。 / p>
答案 2 :(得分:0)
再一次,我刚刚犯了一个愚蠢的错误)我做了一个Web请求,总是会返回一个错误(对于测试),但在我的服务的错误处理程序中,我忘了从Threads列表中删除Thead。现在一切都按照我的预期运作。