Java 无法使用asyncTask.cancel()
我有一个dataGetter类,我在其中加载必要的数据(url地址、电子邮件等的一部分),然后调用AsyncTask。 我使用抽屉菜单,在创建时,每个片段都从新线程调用dataGetter。如果我在片段之间快速切换(在AsyncTask完成之前),数据将混合(在新片段中,我将释放前一个片段中的数据)。 我已尝试使用AsyncTask.cancel,但总是出现错误Java 无法使用asyncTask.cancel(),java,android,android-asynctask,Java,Android,Android Asynctask,我有一个dataGetter类,我在其中加载必要的数据(url地址、电子邮件等的一部分),然后调用AsyncTask。 我使用抽屉菜单,在创建时,每个片段都从新线程调用dataGetter。如果我在片段之间快速切换(在AsyncTask完成之前),数据将混合(在新片段中,我将释放前一个片段中的数据)。 我已尝试使用AsyncTask.cancel,但总是出现错误 public class dataGetter { @SuppressLint("StaticFieldLeak")
public class dataGetter {
@SuppressLint("StaticFieldLeak")
public static Context context;
private static String siteURL;
private static String domain;
private static boolean login;
private static String email;
private static String password;
private static AsyncRetrieve asyncRetrieve;
public static String getData(Context context, String url, String domain, boolean login, String email, String password) {
dataGetter.context = context;
dataGetter.siteURL = url;
dataGetter.domain = domain;
dataGetter.login = login;
dataGetter.email = email;
dataGetter.password = password;
String result = "";
try {
if (asyncRetrieve != null)
asyncRetrieve.cancel(true);
asyncRetrieve = new AsyncRetrieve();
result = asyncRetrieve.execute().get();
}
catch (ExecutionException | InterruptedException e) {
Sentry.capture(e);
e.printStackTrace();
}
return result;
}
public static class AsyncRetrieve extends AsyncTask<String, Void, String> {
HttpsURLConnection conn;
URL url = null;
// This method does not interact with UI, You need to pass result to onPostExecute to display
@Override
protected String doInBackground(String... params) {
.....
}
}
}
我试图在互联网上搜索,但不幸的是什么都没有。
是否有人建议我如何取消asynctask,以便前一个片段中的数据不会出现在新的任务中
事先非常感谢
编辑
第一个片段“域”
getData()方法
最新错误
I/System.out: On Destroy
E/AndroidRuntime: FATAL EXCEPTION: Thread-12
Process: com.example.wedos, PID: 9115
java.util.concurrent.CancellationException
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:193)
at android.os.AsyncTask.get(AsyncTask.java:542)
at com.example.wedos.dataGetter.getData(dataGetter.java:45)
at com.example.wedos.ui.cash.CashFragment.getData(CashFragment.java:90)
at com.example.wedos.ui.cash.CashFragment.access$200(CashFragment.java:25)
at com.example.wedos.ui.cash.CashFragment$2.run(CashFragment.java:59)
at java.lang.Thread.run(Thread.java:764)
D/io.sentry.android.event.helper.AndroidEventBuilderHelper: Proguard UUIDs file not found.
W/System.err: SLF4J: Failed to load class "org.slf4j.impl.StaticMDCBinder".
SLF4J: Defaulting to no-operation MDCAdapter implementation.
SLF4J: See http://www.slf4j.org/codes.html#no_static_mdc_binder for further details.
W/System.err: java.lang.InterruptedException
at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:420)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at android.os.AsyncTask.get(AsyncTask.java:542)
at com.example.wedos.dataGetter.getData(dataGetter.java:45)
at com.example.wedos.ui.domains.DomainsFragment.getDetails(DomainsFragment.java:198)
at com.example.wedos.ui.domains.DomainsFragment.access$100(DomainsFragment.java:38)
at com.example.wedos.ui.domains.DomainsFragment$1.run(DomainsFragment.java:76)
at java.lang.Thread.run(Thread.java:764)
I/Process: Sending signal. PID: 9115 SIG: 9
我建议删除
dataGetter
类,并删除运行AsyncTask
的额外线程。由于处理API响应的方式取决于片段,因此应在单独的文件中创建公共基类,例如AsyncReceiver
public class AsyncRetrieve extends AsyncTask<String, Void, String> {
private Context context;
private Domain domain;
// etc.
public AsyncRetrieve(Context context, String domain, boolean login, String email, String password) {
this.context = context;
this.url = url;
this.domain = domain;
// etc.
}
@Override
public String doInBackground(String... params) {
return fetchData("domainList");
}
private String fetchData(String url) {
// do what you originally did in the old doInBackground
// of the old AsyncRetriever class, but use the url argument
// passed to this method
return result;
}
}
您确定在取消时引发异常吗?能否在task.cancel()前后添加一些日志消息以进行验证?您是否检查AsyncTask
中的isCancelled
?如果我调用asynctrieve.cancel(true)
在一个片段的onDestroy
方法中,打开另一个片段,应用程序崩溃并显示引用dataGetter类中某行的错误(result=asyncRetrieve.execute().get();
)是否可以添加片段类的onCreate
和onDestroy
方法?好,为什么有一个额外的线程来启动异步任务
?您应该在onCreateView
中执行AsyncTask
,并在AsyncTask
的onPostExecute
方法中更新视图。如果我从onCreateView调用AsyncTask,应用程序将冻结。我必须从一个新线程调用以在后台执行该进程
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
//new ViewModelProvider(this).get(CashViewModel.class);
View root = inflater.inflate(R.layout.fragment_cash, container, false);
context = root.getContext();
setHasOptionsMenu(true);
textView = root.findViewById(R.id.cash_amount);
progressBar = root.findViewById(R.id.loading);
linearLayout = root.findViewById(R.id.CashLinearLayout);
Button cashHistory = root.findViewById(R.id.showHistory);
cashHistory.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int index = result.indexOf(' ');
Intent i = new Intent(context, CashHistoryActivity.class);
i.putExtra("CURRENCY", result.substring(index));
startActivity(i);
}
});
thread = new Thread(new Runnable() {
@Override
public void run() {
getData();
}
});
thread.start();
return root;
}
result = dataGetter.getData(context, "cashCheck", "", false, "", "");
I/System.out: On Destroy
E/AndroidRuntime: FATAL EXCEPTION: Thread-12
Process: com.example.wedos, PID: 9115
java.util.concurrent.CancellationException
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:193)
at android.os.AsyncTask.get(AsyncTask.java:542)
at com.example.wedos.dataGetter.getData(dataGetter.java:45)
at com.example.wedos.ui.cash.CashFragment.getData(CashFragment.java:90)
at com.example.wedos.ui.cash.CashFragment.access$200(CashFragment.java:25)
at com.example.wedos.ui.cash.CashFragment$2.run(CashFragment.java:59)
at java.lang.Thread.run(Thread.java:764)
D/io.sentry.android.event.helper.AndroidEventBuilderHelper: Proguard UUIDs file not found.
W/System.err: SLF4J: Failed to load class "org.slf4j.impl.StaticMDCBinder".
SLF4J: Defaulting to no-operation MDCAdapter implementation.
SLF4J: See http://www.slf4j.org/codes.html#no_static_mdc_binder for further details.
W/System.err: java.lang.InterruptedException
at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:420)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at android.os.AsyncTask.get(AsyncTask.java:542)
at com.example.wedos.dataGetter.getData(dataGetter.java:45)
at com.example.wedos.ui.domains.DomainsFragment.getDetails(DomainsFragment.java:198)
at com.example.wedos.ui.domains.DomainsFragment.access$100(DomainsFragment.java:38)
at com.example.wedos.ui.domains.DomainsFragment$1.run(DomainsFragment.java:76)
at java.lang.Thread.run(Thread.java:764)
I/Process: Sending signal. PID: 9115 SIG: 9
public class AsyncRetrieve extends AsyncTask<String, Void, String> {
private Context context;
private Domain domain;
// etc.
public AsyncRetrieve(Context context, String domain, boolean login, String email, String password) {
this.context = context;
this.url = url;
this.domain = domain;
// etc.
}
@Override
public String doInBackground(String... params) {
return fetchData("domainList");
}
private String fetchData(String url) {
// do what you originally did in the old doInBackground
// of the old AsyncRetriever class, but use the url argument
// passed to this method
return result;
}
}
public class DomainsFragment extends Fragment {
private DomainsAsyncReceiver receiver;
// example text view that is updated on results
private TextView tv_results;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// instantiate your views
// e.g.
tv_results = findViewById(R.id.tv_results);
// etc.
// instantiate the async task
receiver = new DomainsAsyncReceiver(domain, url, etc.);
receiver.execute();
}
@Override
public void onDestroy() {
super.onDestroy();
// cancel the async task
receiver.cancel(true);
}
private class DomainsAsyncReceiver extends AsyncRetrieve {
@Override
protected String doInBackground(String... params) {
String result = fetchData("domainList");
// do something with the result, e.g.
String details = fetchData("domainDetails");
return details;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
tv_results.setText(result);
}
}
}