跳过了60帧! 应用程序可能在其主线程上做了太多的工作

我正在一个应用程序,应该从Web服务得到一个JSON响应,并写一个列表视图中的每一个元素,我已经读了,我应该与AsyncTask获得HTTP响应,我做到了,我可以从Web服务检索数据并在TextViews中显示它们。 但是,当我尝试在列表视图中显示元素时,它不显示任何内容,并在logcat中给我以下消息: 06-05 19:44:27.418: I/Choreographer(20731): Skipped 60 frames! The application may be doing too much work on its main thread. 06-05 19:44:27.418: I/Choreographer(20731): Skipped 60 frames! The application may be doing too much work on its main thread.

这是我的主要代码:

 public class MainActivity extends Activity { private static JsonObject response = new JsonObject(); private ArrayList<SearchResults> results = new ArrayList<SearchResults>(); private SearchResults sr1 = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new LoginAction().execute(""); ArrayList<SearchResults> searchResults = results; final ListView lv1 = (ListView) findViewById(R.id.ListView01); lv1.setAdapter(new MyCustomBaseAdapter(this, searchResults)); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } private class LoginAction extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { Map<String, String> callArgs = new HashMap<String, String>(1); callArgs.put("suuid", "dtr0bdQGcqwSh3QO7fVwgVfBNWog6mvEbAyljlLX9E642Yfmur"); try { response = EventPulseCloud.call("ListEvents", callArgs); } catch (HttpClientException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JsonException e) { e.printStackTrace(); } return response.get("Type").toString(); } protected void onPostExecute(String result) { if(result.equals("success")) { JsonArray records = null; try { records = response.getObject ("Data").getArray ("Records"); } catch (JsonException e) { e.printStackTrace(); } for(int i = 0; i < records.count(); i++) { JsonObject record = (JsonObject) records.get(i); sr1 = new SearchResults(); sr1.setAddress(record.get("address").toString()); results.add(sr1); } } } } } 

我的列表适配器:

 public class MyCustomBaseAdapter extends BaseAdapter { private static ArrayList<SearchResults> searchArrayList; private LayoutInflater mInflater; public MyCustomBaseAdapter(Context context, ArrayList<SearchResults> results) { searchArrayList = results; mInflater = LayoutInflater.from(context); } public int getCount() { return searchArrayList.size(); } public Object getItem(int position) { return searchArrayList.get(position); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = mInflater.inflate(R.layout.custom_row_view, null); holder = new ViewHolder(); holder.txtAddress = (TextView) convertView.findViewById(R.id.address); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.txtAddress.setText(searchArrayList.get(position).getAddress()); return convertView; } static class ViewHolder { TextView txtAddress; } } 

最后,SearchResults.java:

 public class SearchResults { private String address = ""; public void setAddress(String address) { this.address = address; } public String getAddress() { return address; } } 

那么,我做错了什么? 你有这个想法吗?

谢谢。

Solutions Collecting From Web of "跳过了60帧! 应用程序可能在其主线程上做了太多的工作"

 private class LoginAction extends AsyncTaskList<String, Void, ArrayList<SearchResult>> { @Override protected ArrayList<SearchResult> doInBackground(String... params) { List<SearchResults> resultList = new ArrayList<SearchResults>(); Map<String, String> callArgs = new HashMap<String, String>(1); callArgs.put("suuid", "dtr0bdQGcqwSh3QO7fVwgVfBNWog6mvEbAyljlLX9E642Yfmur"); try { response = EventPulseCloud.call("ListEvents", callArgs); } catch (HttpClientException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JsonException e) { e.printStackTrace(); } //See here I am running the loop in the background so its not on the main thread, then passing the list off to the onpostexecute that way all the main thread does is set the adapter list and notify it of the data update and the list should be updated on the screen if( response.get("Type").toString().equals("success")) { JsonArray records = null; try { records = response.getObject ("Data").getArray ("Records"); } catch (JsonException e) { e.printStackTrace(); } for(int i = 0; i < records.count(); i++) { JsonObject record = (JsonObject) records.get(i); sr1 = new SearchResults(); sr1.setAddress(record.get("address").toString()); resultList.add(sr1); } } return resultList; } protected void onPostExecute(ArrayList<SearchResult> resultList) { setListItems(resultList); } } } 

在所有其他全局variables之前添加此行

  //here you want to create an adapter var with your base adapter so you can set it the updated list later when you have populated data from the internet ArrayList<SearchResults> searchResults = new ArrayList<SearchResults>(); MyCustomBaseAdapter adapter = new MyCustomBaseAdapter(this, searchResults) 

粘贴这个你的oncreate方法(replace)

 //here is just the code to update your main method to reflect all the changes I made @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new LoginAction().execute(""); final ListView lv1 = (ListView) findViewById(R.id.ListView01); lv1.setAdapter(adapter); } 

并将此方法添加到适配器(MyCustomnBaseAdapter类)代码中

 public void setListItems(ArrayList<SearchResult> newList) { searchArrayList = newList; notifyDataSetChanged(); } 

onPostExecute()发生在主UI线程上。 看起来你仍然在这个方法中做了相当多的工作,应该在UI线程上完成,比如处理响应,遍历JSON对象等。在doInBackground()做这个,并且返回一个结果列表,所以onPostExecute唯一需要做的就是将新项目传递给你的列表适配器。

另外,请不要使用与您的适配器所持有的ArrayList相同的ArrayList。 如果由于某种原因,适配器发现没有调用notifyDataSetChanged()数据已经改变,它可能会崩溃(或至less显示奇怪的行为)。 在你的AsyncTask中创build一个新的ArrayList,然后把它放在你的Adapter中并从onPostExecute中调用它:

 public void setListItems(ArrayList<SearchResult> newList) { searchArrayList = newList; notifyDataSetChanged(); }