即使AsyncTask处理任务,主UI也会冻结

时间:2012-12-10 20:24:05

标签: android service android-asynctask

我在后台运行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);

4 个答案:

答案 0 :(得分:8)

  

即使工作是在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();
}

NetTask的{​​{1}}方法中,然后移除onPostExecute()。现在你的AsyncTask不会绑定主线程。

答案 1 :(得分:4)

这是因为

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

呼叫。

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

onPostExecute() 

并在那里处理结果。

答案 2 :(得分:0)

请勿致电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

答案 3 :(得分:0)

我遇到了类似的问题并弄清楚发生了什么。如果您在 onProgressUpdate 中添加'for for循环' sleep ,则此代码不会冻结用户界面,,然后是用户界面在此过程中将被冻结。

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");
    }
}