【问题标题】:Main UI freezes even when tasks are handled by AsyncTask即使任务由 AsyncTask 处理,主 UI 也会冻结
【发布时间】:2012-12-10 20:24:05
【问题描述】:

我制作了Service,它在后台运行,使用AsyncTask从互联网收集数据并将它们存储在Shared Preferences中。即使工作是在AsyncTask 完成的,它仍然会冻结我的主要活动。

这是服务的代码:

public class GetterService extends Service {

    SharedPreferences.Editor editor;
    HashMap<Integer,String> links = new HashMap<Integer,String>();

    @Override
    public void onCreate() {
        editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
        populateLinks();
    }

    private void populateLinks(){
        // Here I add links to HashMap
    }

    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(this, "GetterService ON BIND", Toast.LENGTH_LONG).show();
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "GetterService ON DESTROY", Toast.LENGTH_LONG).show();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        doTasks();

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Toast.makeText(this, "GetterService ON UNBIND", Toast.LENGTH_LONG).show();
        return super.onUnbind(intent);
    }

    private void doTasks(){
        for (Integer in : links.keySet()) {

            Document doc = null;

            try {
                doc = new NetTask().execute(links.get(in)).get();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            if (doc != null) {
                Elements names = doc.select("strong, li");

                if(names != null && names.size() > 0) {
                    for (int j = 0; j < names.size(); j++) {
                        editor.putString("header"+j, names.get(j).text().toString());
                    }
                }
                editor.commit();
            }
        }   
    }

    public class NetTask extends AsyncTask<String, Integer, Document>
    {
        @Override
        protected Document doInBackground(String... params)
        {
            Document doc = null;
            try {
                doc = Jsoup.connect(params[0]).timeout(5000).get();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return doc;
        }
    }
}

这是我从主要活动启动服务的方式:

Intent startServiceIntent = new Intent(this, GetterService.class);
        this.startService(startServiceIntent);

【问题讨论】:

    标签: android service android-asynctask


    【解决方案1】:

    即使工作是在 AsyncTask 中完成的,它仍然会冻结我的主要活动。

    你正在使用get()

    doc = new NetTask().execute(links.get(in)).get();
    

    get() 会阻塞 UI 线程,直到 AsyncTask 完成,对我来说,这种方法违背了使用 AsyncTask 的目的......


    你应该移动这个逻辑:

    if (doc != null) {
        Elements names = doc.select("strong, li");
    
        if(names != null && names.size() > 0) {
            for (int j = 0; j < names.size(); j++) {
                editor.putString("header"+j, names.get(j).text().toString());
            }
        }
        editor.commit();
    }
    

    在您的NetTaskonPostExecute() 方法中并删除get()。现在你的 AsyncTask 不会绑定主线程了。

    【讨论】:

    • 这确实有帮助,有点。现在唯一的事情是,当我在服务执行任务时尝试转到另一个活动时,主要活动会冻结。知道为什么吗?
    • 你试过取消GetterService#onDestroy()里面的活动下载吗? Android - Cancel AsyncTask Forcefully
    • 不,但我已经找到了导致此问题的原因,并为此打开了新的客户。不过还是谢谢。
    【解决方案2】:

    这是因为

    new NetTask().execute(links.get(in)).get();
    

    打电话。

    AsyncTask.get() 阻塞,直到异步调用完成。要实现异步,您需要实现

    onPostExecute() 
    

    并在那里处理结果。

    【讨论】:

      【解决方案3】:

      不要拨打get(),只需拨打execute()。实现并覆盖 onPostExecute() 以将 Document 对象作为参数。 onPostExecute()doInBackground() 返回时自动调用。 onPostExecute() 中的代码在 UI 线程上执行,因此您可以通过这种方式与 UI 进行交互。

      我建议您查看本文档中的 AsyncTask 部分,http://developer.android.com/guide/components/processes-and-threads.html 和此处的 AsyncTask API 页面,http://developer.android.com/reference/android/os/AsyncTask.html

      【讨论】:

        【解决方案4】:

        我遇到了类似的问题,并弄清楚发生了什么。此代码不会冻结 UI,如果您将 'for loop'sleep 放入 onProgressUpdate,然后 UI在此过程中将被冻结。

        public class Karaoke extends AsyncTask<Void, Integer, Void> {
            private Handler mHandler = new Handler(Looper.getMainLooper());
            protected Void doInBackground(Void... urls) {
                animating = true;
                {
                    for (int i = 0;i < 6; i++)
                    {
                        publishProgress(i);
                        try
                        {
                            Thread.sleep(1000);
                            publishProgress(i);
                        }
                        catch (Exception xx){
                        }
                    }
                }
                animating = false;
                return null;
            }
            @Override
            protected void onProgressUpdate(Integer... values) {
                if (light)
                {
                    light = false;
                    iv_array[findview(egtxts[values[0]].getText() + "")].setImageResource(onpress);
                }
                else
                {
                    light = true;
                    iv_array[findview(egtxts[values[0]].getText() + "")].setImageResource(onup);
                }
            }
        
            protected void onPostExecute(Long result) {
                //showDialog("Downloaded " + result + " bytes");
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-04-28
          • 1970-01-01
          • 2011-10-16
          • 1970-01-01
          • 2021-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多