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