即使异步任务在处理,主界面仍然会冻结。

4

我制作了一个Service,它在后台使用AsyncTask从互联网收集数据并将其存储在Shared Preferences中。尽管工作是在AsyncTask中完成的,但它仍然会冻结我的主活动。

这是Service的代码:

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个回答

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不会阻塞主线程了。

这确实有所帮助。现在唯一的问题是,当服务正在执行任务时,主活动在尝试转到另一个活动时会冻结。你知道为什么吗? - Rohit Malish
你尝试在 GetterService#onDestroy() 中取消活动下载了吗?Android - 强制取消AsyncTask - Sam
不用了,但我已经找出了导致这个问题的原因,并为此打开了新的问题。还是谢谢你。 - Rohit Malish

4
由于这个原因,与IT技术有关。
new NetTask().execute(links.get(in)).get();

调用。

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

onPostExecute() 

并在那里处理结果。

0

我曾经遇到过类似的问题,后来找出了问题所在。这段代码不会冻结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");
    }
}

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接