我应该在什么生命周期状态下在 Fragment 中执行异步任务?
In what lifecycle state should I execute an Async Task in Fragment?
加载片段时,我必须对远程服务器进行昂贵的调用。我使用默认的 Dashboard activity 和 NavigationView 来更改片段。但是,无论何时加载片段,它都会在执行包含 SOAP 请求代码的 AsyncTask 时冻结 UI 几秒钟。
我已经尝试从 onAttach()
和 onStart()
执行 AsyncTask 但它仍然冻结 UI.
如何修复 UI 冻结?
编辑:- 异步任务代码:-
private class BindTreasuryTask extends AsyncTask<Void,Void,ArrayList<TreasuryData>> {
private boolean NO_INTERNET;
@Override
protected ArrayList<TreasuryData> doInBackground(Void... voids) {
try {
// SOAP Call returns a JSONArray
JSONArray jsonArray = apiHandler.performBindTreasury(payeeid);
ArrayList<TreasuryData> td = new ArrayList<>();
td.add(new TreasuryData("Select a treasury","none","none"));
for(int i =0; i<jsonArray.size(); i++){
JSONObject j = (JSONObject) jsonArray.get(i);
td.add(new TreasuryData(j.get("TREASURY_NAME"),j.get("TREAS_CODE"),j.get("SCHEMA_NM")));
}
return td;
} catch (IOException e) {
NO_INTERNET = true;
e.printStackTrace();
} catch (XmlPullParserException | ParseException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(ArrayList<TreasuryData> treasuryData ) {
if (treasuryData == null){
if (NO_INTERNET){
Toast.makeText(getActivity(),"No Internet Connection",Toast.LENGTH_LONG).show();
}
} else {
ArrayList<String> treasury = new ArrayList<>();
for(int i=0;i<treasuryData.size();i++){
treasury.add(treasuryData.get(i).getTreasuryName());
}
setUpView();
}
}
}
onActivityCreated()
可以是您的选择,昂贵的工作应该在 doInBackGround()
方法中完成。
正如 Ashok 回答的那样,您可以在 onActivityCreated() 方法中调用 AsyncTask。您可以使用线程或处理程序以 1-2 秒的延迟启动 SOAP 请求,这样可以避免在调用 Api 时冻结片段。或者,如果 UI 在您从导航抽屉切换片段时冻结,那么您可能必须管理自己的片段队列。
加载片段时,我必须对远程服务器进行昂贵的调用。我使用默认的 Dashboard activity 和 NavigationView 来更改片段。但是,无论何时加载片段,它都会在执行包含 SOAP 请求代码的 AsyncTask 时冻结 UI 几秒钟。
我已经尝试从 onAttach()
和 onStart()
执行 AsyncTask 但它仍然冻结 UI.
如何修复 UI 冻结?
编辑:- 异步任务代码:-
private class BindTreasuryTask extends AsyncTask<Void,Void,ArrayList<TreasuryData>> {
private boolean NO_INTERNET;
@Override
protected ArrayList<TreasuryData> doInBackground(Void... voids) {
try {
// SOAP Call returns a JSONArray
JSONArray jsonArray = apiHandler.performBindTreasury(payeeid);
ArrayList<TreasuryData> td = new ArrayList<>();
td.add(new TreasuryData("Select a treasury","none","none"));
for(int i =0; i<jsonArray.size(); i++){
JSONObject j = (JSONObject) jsonArray.get(i);
td.add(new TreasuryData(j.get("TREASURY_NAME"),j.get("TREAS_CODE"),j.get("SCHEMA_NM")));
}
return td;
} catch (IOException e) {
NO_INTERNET = true;
e.printStackTrace();
} catch (XmlPullParserException | ParseException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(ArrayList<TreasuryData> treasuryData ) {
if (treasuryData == null){
if (NO_INTERNET){
Toast.makeText(getActivity(),"No Internet Connection",Toast.LENGTH_LONG).show();
}
} else {
ArrayList<String> treasury = new ArrayList<>();
for(int i=0;i<treasuryData.size();i++){
treasury.add(treasuryData.get(i).getTreasuryName());
}
setUpView();
}
}
}
onActivityCreated()
可以是您的选择,昂贵的工作应该在 doInBackGround()
方法中完成。
正如 Ashok 回答的那样,您可以在 onActivityCreated() 方法中调用 AsyncTask。您可以使用线程或处理程序以 1-2 秒的延迟启动 SOAP 请求,这样可以避免在调用 Api 时冻结片段。或者,如果 UI 在您从导航抽屉切换片段时冻结,那么您可能必须管理自己的片段队列。