4

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

4 回答 4

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

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

于 2012-12-10T20:27:49.363 回答
4

这是因为

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

称呼。

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

onPostExecute() 

并在那里处理结果。

于 2012-12-10T20:29:16.683 回答
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

于 2012-12-10T20:37:51.410 回答
0

我有类似的问题,并弄清楚发生了什么。这段代码不会冻结 UI,如果你在onProgressUpdate中放置“for loop”休眠,那么 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");
    }
}
于 2013-12-13T10:04:59.737 回答