我应该在 Fragment 中的啥生命周期状态下执行异步任务?

Posted

技术标签:

【中文标题】我应该在 Fragment 中的啥生命周期状态下执行异步任务?【英文标题】:In what lifecycle state should I execute an Async Task in Fragment?我应该在 Fragment 中的什么生命周期状态下执行异步任务? 【发布时间】:2020-01-15 12:52:36 【问题描述】:

加载片段时,我必须对远程服务器进行昂贵的调用。我正在使用带有 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();
            
        
    

【问题讨论】:

AnsyncTask 是一个 UI 非阻塞调用。你能在这里分享你的异步任务代码吗?所以我们可以看看 考虑为您的异步任务添加进度条。在 preExecute 你让它可见,你在 doIOnBackground 中调用,如果你想你可以更新它的进度,或者将它设置为不确定,当后台任务完成时,填充你的视图并去掉进度条。 【参考方案1】:

正如 Ashok 回答的那样,您可以在 onActivityCreated() 方法中调用 AsyncTask。您可以使用线程或处理程序以 1-2 秒的延迟启动 SOAP 请求,这样可以避免在调用 Api 时冻结片段。或者,如果您从导航抽屉切换片段时 UI 冻结,那么您可能必须管理自己的片段队列。

【讨论】:

虽然我一直在寻找更好的东西,因为我已经想到了这一点,但看起来我只能通过这个解决方案。【参考方案2】:

onActivityCreated() 可以是你的选择,昂贵的工作应该在doInBackGround() 方法中完成。

【讨论】:

不幸的是它仍然像以前一样冻结。

以上是关于我应该在 Fragment 中的啥生命周期状态下执行异步任务?的主要内容,如果未能解决你的问题,请参考以下文章

Fragment生命周期总结

android fragment相互切换的时候生命周期怎么走

关于FragmentManager动态管理Fragment时Fragment生命周期的探究

从0系统学Android--4.2 Fragment 生命周期

Android Fragment生命周期及静态加载

Activity与Fragment的生命周期详解