Here's my code (simplified a little bit):
Service
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);
}
}
Thread
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();
}
}
I also have an Activity
which send Intent
each time onCreate
method gets called to start the task. The issue is that after several restarts I get about 300rb leaked and even if I call GC from Eclipse I didn't get freed. What am I doing wrong?
UPDATE Activity code:
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;
}
}
As you can see it is very simple.