【发布时间】:2019-09-10 15:30:54
【问题描述】:
public class CopyService extends Service {
private List<CustomFile> taskList;
private AsyncTask fileTask;
@Override
public void onCreate() {
super.onCreate();
taskList = new ArrayList<>();
fileTask = new fileTaskAsync();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String filePath = intent.getStringExtra("filePath");
String fileType = intent.getStringExtra("fileType");
String taskType = intent.getStringExtra("taskType");
String fileName = intent.getStringExtra("fileName");
CustomFile customFile = new CustomFile();
customFile.filePath = filePath;
customFile.fileType = fileType;
customFile.taskType = taskType;
customFile.fileName = fileName;
taskList.add(customFile);
Notification notification = getNotification();
startForeground(787, notification);
if (fileTask.getStatus() != AsyncTask.Status.RUNNING) {
CustomFile current = taskList.get(0);
taskList.remove(current);
fileTask = new fileTaskAsync().execute(current);
}
stopSelf();
return START_NOT_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private class fileTaskAsync extends AsyncTask<CustomFile, Void, String> {
@Override
protected String doInBackground(CustomFile... customFiles) {
CustomFile customFile = customFiles[0];
FileUtils.doFileTask(customFile.filePath, customFile.fileType,
customFile.taskType);
return customFile.fileName;
}
@Override
protected void onPostExecute(String name) {
sendResult(name);
if (!taskList.isEmpty()) {
CustomFile newCurrent = taskList.get(0);
taskList.remove(newCurrent);
fileTask = new fileTaskAsync().execute(newCurrent);
}
}
}
private void sendResult(String name) {
Intent intent = new Intent("taskStatus");
intent.putExtra("taskName", name);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
我需要在一个服务中一个一个地执行多个任务。任务是复制或移动本地文件。假设,用户正在复制一个大文件,他想复制或移动其他文件。后续的任务需要一个一个排队执行。
目前,我正在服务内创建一个列表并运行一个异步任务。在 onPostExecute 中,我检查列表中的剩余任务并从那里再次启动异步任务。如代码所示。
但是,我担心内存泄漏。而且我对编程很陌生,所以我不知道在这种情况下最好的做法是什么。
我不能使用 IntentService,因为我希望即使用户点击主页按钮打开其他应用程序也能继续执行任务。
【问题讨论】:
-
你在你的服务中做什么样的工作?你能把你写的代码贴出来吗?
-
@PPartisan 我编辑了我的帖子并包含了代码。我之前没有发布代码的原因是因为我想知道一个通用的解决方案,不管代码是什么。但是,我想我的问题有点不清楚。
-
我认为你的解决方案是合理的。对于您正在做的工作(需要立即执行的长期工作)
ForegroundService是最好的解决方案。作为AsyncTask的替代方案,您可以使用ExecutorService或(如果您不介意加入额外的库)RxJava。我可能会完成所有需要完成的工作并立即执行它,而不是为每个操作杀死/重新启动多个任务。你也可以让你的AsyncTask类static,所以它不包含对Service的隐式引用。如果需要,请使用application context。 -
你能告诉我如何使用应用程序上下文吗?是 getApplication() 还是 getApplicationContext() ?
-
使你的内部类
static(非静态嵌套类持有对其包含类的隐式引用,当封闭类扩展@987654331时,这可能导致内存泄漏@(Service确实如此)并且涉及线程),将Service作为构造函数参数传入,并且只保留对context.getApplicationContext()的引用。 Application Context 是事实上的单例,因此您无需担心“泄漏”它。我会填写答案。
标签: android android-asynctask android-service android-intentservice