如何在 Android 中取消 AsyncTask
How to cancle AsyncTask in Android
在我的应用程序中,我有 2 个 AsyncTask
方法,我想在 activity
转到 onPause
时取消此 AsyncTask
s 并在 onResume
从头开始.
我写了下面的代码,我按下主页按钮,应用程序转到 onPause
并再次从最近的应用程序
打开这个应用程序
我的意思是调用 onPause
和 onResume
!
但是当再次应用运行时(来自最近的应用),调用onResume
但不会从头开始AsyncTask
!
我的代码:
@Override
protected void onResume() {
super.onResume();
new Handler(getMainLooper()).postDelayed(() -> {
//Get compress or upload
if (bundle == null) {
//Get video from file
getLoadOriginalVideos();
testIsSendPlans = testId;
}
}, 500);
}
@Override
protected void onPause() {
super.onPause();
new GetOriginalVideosAsync().cancel(true);
new GetCompressedVideosAsync().cancel(true);
}
private void getLoadOriginalVideos() {
if (videoList.isEmpty()) {
File directory = new File(Environment.getExternalStorageDirectory() + File.separator + APPDIR);
ArrayList<File> filesList = new ArrayList<File>();
if (directory.isDirectory() && directory.exists()) {
filesList.addAll(Arrays.asList(getOriginalVideos(directory.listFiles())));
}
new GetOriginalVideosAsync().execute(filesList.toArray(new File[filesList.size()]));
}
}
@SuppressLint("StaticFieldLeak")
class GetOriginalVideosAsync extends AsyncTask<File[], Integer, ArrayList<Video>> {
File[] files;
ContentResolver resolver;
GetOriginalVideosAsync() {
resolver = context.getContentResolver();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(ArrayList<Video> videos) {
Collections.sort(videos, Collections.reverseOrder());
getLastOriginalVideo(addVideos(videos));
}
private ArrayList<Video> addVideos(ArrayList<Video> videos) {
return new ArrayList<>(videos);
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected ArrayList<Video> doInBackground(File[]... arg) {
files = arg[0];
for (File file : files) {
if (!file.isDirectory() && isVideoFile(file.getPath())) {
videoList.add(new Video(file.getName(), file, new Date(file.lastModified())));
}
}
return videoList;
}
}
@SuppressLint("StaticFieldLeak")
class GetCompressedVideosAsync extends AsyncTask<File[], Integer, ArrayList<Video>> {
File[] files;
ContentResolver resolver;
GetCompressedVideosAsync() {
resolver = context.getContentResolver();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(ArrayList<Video> videos) {
Collections.sort(videos, Collections.reverseOrder());
getLastCompressedVideo(addVideos(videos));
}
private ArrayList<Video> addVideos(ArrayList<Video> videos) {
return new ArrayList<>(videos);
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected ArrayList<Video> doInBackground(File[]... arg) {
files = arg[0];
for (File file : files) {
if (!file.isDirectory() && isVideoFile(file.getPath())) {
videoListCompressed.add(new Video(file.getName(), file, new Date(file.lastModified())));
}
}
return videoListCompressed;
}
}
我该如何修复它并在 onResume
从头开始 这个 AsyncTask
s ?
当你取消asynctask时,虽然它被取消了。您的 asyncTask 将保持 运行 直到 doInBackGround() 完成其工作。
因此,对于您的 GetOriginalVideosAsync
,请在 doInBackground
中执行此操作:
@Override
protected ArrayList<Video> doInBackground(File[]... arg) {
files = arg[0];
for (File file : files) {
//add this
if(isCancelled){
return null;
}
if (!file.isDirectory() && isVideoFile(file.getPath())) {
videoList.add(new Video(file.getName(), file, new Date(file.lastModified())));
}
}
return videoList;
}
为了您的 GetCompressedVideosAsync
,请在 doInBackground
中执行此操作:
@Override
protected ArrayList<Video> doInBackground(File[]... arg) {
files = arg[0];
for (File file : files) {
//add this
if(isCancelled){
return null;
}
if (!file.isDirectory() && isVideoFile(file.getPath())) {
videoListCompressed.add(new Video(file.getName(), file, new Date(file.lastModified())));
}
}
return videoListCompressed;
}
更新
在我告诉您的同一位置的两个任务中尝试此操作:
if(isCancelled){
break;
}
更新 2
看你的asyncTaks一定是activity
的成员变量
class MyActivity extends ........{
private GetOriginalVideosAsync orginalTask;
private GetCompressedVideosAsync compressedTask;
.......
}
像这样调用暂停:
@Override
protected void onPause() {
orginalTask.cancel(true);
compressedTask.cancel(true);
super.onPause();
}
和
private void getLoadOriginalVideos() {
if (videoList.isEmpty()) {
File directory = new File(Environment.getExternalStorageDirectory() + File.separator + APPDIR);
ArrayList<File> filesList = new ArrayList<File>();
if (directory.isDirectory() && directory.exists()) {
filesList.addAll(Arrays.asList(getOriginalVideos(directory.listFiles())));
}
orginalTask = new GetOriginalVideosAsync();
orginalTask.execute(filesList.toArray(new File[filesList.size()]));
}
}
可以随时通过调用 cancel(boolean) 来取消任务。调用此方法将导致对 isCancelled() 的后续调用为 return true。调用此方法后,在 doInBackground(java.lang.Object[]) returns 之后将调用 onCancelled(java.lang.Object),而不是 onPostExecute(java.lang.Object)。为确保尽快取消任务,您应该始终定期从 doInBackground(java.lang.Object[]) 检查 isCancelled() 的 return 值,如果可能(例如在循环内)。
来源:https://developer.android.com/reference/android/os/AsyncTask
您在代码中遇到的问题是您正在创建一个新实例,而不是使用您创建的同一个实例 ,您可以通过在 class 级别而不是 method/block 级别声明实例 全局可访问 来实现。
问题
...
new GetOriginalVideosAsync().execute(...)
new GetCompressedVideosAsync().execute(...)
...
super.onPause();
new GetOriginalVideosAsync().cancel(true);
new GetCompressedVideosAsync().cancel(true);
...
正确的方法
...
getOriginalVideosAsync = new GetOriginalVideosAsync(); // Declare this in class level
getOriginalVideosAsync.execute(...) // replace old execute code with the instance
getCompressedVideosAsync = new GetCompressedVideosAsync(); // Declare this in class level
getCompressedVideoAsync.execute(...) // replace old execute code with the instance
...
super.onPause();
getOriginalVideosAsync().cancel(true);
getCompressedVideosAsync().cancel(true);
...
再看看"java global variable vs local variable",希望解释有帮助,干杯。
在我的应用程序中,我有 2 个 AsyncTask
方法,我想在 activity
转到 onPause
时取消此 AsyncTask
s 并在 onResume
从头开始.
我写了下面的代码,我按下主页按钮,应用程序转到 onPause
并再次从最近的应用程序
打开这个应用程序
我的意思是调用 onPause
和 onResume
!
但是当再次应用运行时(来自最近的应用),调用onResume
但不会从头开始AsyncTask
!
我的代码:
@Override
protected void onResume() {
super.onResume();
new Handler(getMainLooper()).postDelayed(() -> {
//Get compress or upload
if (bundle == null) {
//Get video from file
getLoadOriginalVideos();
testIsSendPlans = testId;
}
}, 500);
}
@Override
protected void onPause() {
super.onPause();
new GetOriginalVideosAsync().cancel(true);
new GetCompressedVideosAsync().cancel(true);
}
private void getLoadOriginalVideos() {
if (videoList.isEmpty()) {
File directory = new File(Environment.getExternalStorageDirectory() + File.separator + APPDIR);
ArrayList<File> filesList = new ArrayList<File>();
if (directory.isDirectory() && directory.exists()) {
filesList.addAll(Arrays.asList(getOriginalVideos(directory.listFiles())));
}
new GetOriginalVideosAsync().execute(filesList.toArray(new File[filesList.size()]));
}
}
@SuppressLint("StaticFieldLeak")
class GetOriginalVideosAsync extends AsyncTask<File[], Integer, ArrayList<Video>> {
File[] files;
ContentResolver resolver;
GetOriginalVideosAsync() {
resolver = context.getContentResolver();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(ArrayList<Video> videos) {
Collections.sort(videos, Collections.reverseOrder());
getLastOriginalVideo(addVideos(videos));
}
private ArrayList<Video> addVideos(ArrayList<Video> videos) {
return new ArrayList<>(videos);
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected ArrayList<Video> doInBackground(File[]... arg) {
files = arg[0];
for (File file : files) {
if (!file.isDirectory() && isVideoFile(file.getPath())) {
videoList.add(new Video(file.getName(), file, new Date(file.lastModified())));
}
}
return videoList;
}
}
@SuppressLint("StaticFieldLeak")
class GetCompressedVideosAsync extends AsyncTask<File[], Integer, ArrayList<Video>> {
File[] files;
ContentResolver resolver;
GetCompressedVideosAsync() {
resolver = context.getContentResolver();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(ArrayList<Video> videos) {
Collections.sort(videos, Collections.reverseOrder());
getLastCompressedVideo(addVideos(videos));
}
private ArrayList<Video> addVideos(ArrayList<Video> videos) {
return new ArrayList<>(videos);
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected ArrayList<Video> doInBackground(File[]... arg) {
files = arg[0];
for (File file : files) {
if (!file.isDirectory() && isVideoFile(file.getPath())) {
videoListCompressed.add(new Video(file.getName(), file, new Date(file.lastModified())));
}
}
return videoListCompressed;
}
}
我该如何修复它并在 onResume
从头开始 这个 AsyncTask
s ?
当你取消asynctask时,虽然它被取消了。您的 asyncTask 将保持 运行 直到 doInBackGround() 完成其工作。
因此,对于您的 GetOriginalVideosAsync
,请在 doInBackground
中执行此操作:
@Override
protected ArrayList<Video> doInBackground(File[]... arg) {
files = arg[0];
for (File file : files) {
//add this
if(isCancelled){
return null;
}
if (!file.isDirectory() && isVideoFile(file.getPath())) {
videoList.add(new Video(file.getName(), file, new Date(file.lastModified())));
}
}
return videoList;
}
为了您的 GetCompressedVideosAsync
,请在 doInBackground
中执行此操作:
@Override
protected ArrayList<Video> doInBackground(File[]... arg) {
files = arg[0];
for (File file : files) {
//add this
if(isCancelled){
return null;
}
if (!file.isDirectory() && isVideoFile(file.getPath())) {
videoListCompressed.add(new Video(file.getName(), file, new Date(file.lastModified())));
}
}
return videoListCompressed;
}
更新
在我告诉您的同一位置的两个任务中尝试此操作:
if(isCancelled){
break;
}
更新 2
看你的asyncTaks一定是activity
的成员变量class MyActivity extends ........{
private GetOriginalVideosAsync orginalTask;
private GetCompressedVideosAsync compressedTask;
.......
}
像这样调用暂停:
@Override
protected void onPause() {
orginalTask.cancel(true);
compressedTask.cancel(true);
super.onPause();
}
和
private void getLoadOriginalVideos() {
if (videoList.isEmpty()) {
File directory = new File(Environment.getExternalStorageDirectory() + File.separator + APPDIR);
ArrayList<File> filesList = new ArrayList<File>();
if (directory.isDirectory() && directory.exists()) {
filesList.addAll(Arrays.asList(getOriginalVideos(directory.listFiles())));
}
orginalTask = new GetOriginalVideosAsync();
orginalTask.execute(filesList.toArray(new File[filesList.size()]));
}
}
可以随时通过调用 cancel(boolean) 来取消任务。调用此方法将导致对 isCancelled() 的后续调用为 return true。调用此方法后,在 doInBackground(java.lang.Object[]) returns 之后将调用 onCancelled(java.lang.Object),而不是 onPostExecute(java.lang.Object)。为确保尽快取消任务,您应该始终定期从 doInBackground(java.lang.Object[]) 检查 isCancelled() 的 return 值,如果可能(例如在循环内)。
来源:https://developer.android.com/reference/android/os/AsyncTask
您在代码中遇到的问题是您正在创建一个新实例,而不是使用您创建的同一个实例 ,您可以通过在 class 级别而不是 method/block 级别声明实例 全局可访问 来实现。
问题
...
new GetOriginalVideosAsync().execute(...)
new GetCompressedVideosAsync().execute(...)
...
super.onPause();
new GetOriginalVideosAsync().cancel(true);
new GetCompressedVideosAsync().cancel(true);
...
正确的方法
...
getOriginalVideosAsync = new GetOriginalVideosAsync(); // Declare this in class level
getOriginalVideosAsync.execute(...) // replace old execute code with the instance
getCompressedVideosAsync = new GetCompressedVideosAsync(); // Declare this in class level
getCompressedVideoAsync.execute(...) // replace old execute code with the instance
...
super.onPause();
getOriginalVideosAsync().cancel(true);
getCompressedVideosAsync().cancel(true);
...
再看看"java global variable vs local variable",希望解释有帮助,干杯。