Skipped 60 frames! The application may be doing too much work on its main thread

匿名 (未验证) 提交于 2019-12-03 01:49:02

问题:

I'm working on a App that should get a JSON response from a webservice and write every element in a listview, I have read that I should work with AsyncTask to get the HTTP Response and I did it and I could retrieve data from the webservice and display them in TextViews. But when I try to display elements in a listview it doesn't display anything and gives me the following message in the 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.

here's my main code :

public class MainActivity extends Activity {      private static JsonObject response = new JsonObject();     private ArrayList results = new ArrayList();      private SearchResults sr1 = null;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);          new LoginAction().execute("");            ArrayList 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 {          @Override         protected String doInBackground(String... params) {              Map callArgs = new HashMap(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 

My list adapter :

public class MyCustomBaseAdapter extends BaseAdapter {     private static ArrayList searchArrayList;      private LayoutInflater mInflater;      public MyCustomBaseAdapter(Context context, ArrayList 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;     } } 

and finally, SearchResults.java :

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

So, what do I do wrong ? Do you have an idea about this ?

Thank you.

回答1:

private class LoginAction extends AsyncTaskList> {      @Override     protected ArrayList doInBackground(String... params) {         List resultList =  new ArrayList();          Map callArgs = new HashMap(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  resultList) {           setListItems(resultList);      }    } } 

add this line before the oncreate with all your other global var

   //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 = new ArrayList();          MyCustomBaseAdapter adapter = new MyCustomBaseAdapter(this, searchResults) 

paste this over your oncreate method (replace it)

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

and add this method to the adapter(MyCustomnBaseAdapter class) code

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


回答2:

onPostExecute() happens on the Main UI thread. It looks like you are still doing a fair amount of work in that method that should be done off the UI thread, i.e. processing the response, iterating over JSON objects, etc. Do that in doInBackground() and have that return a list of results, so the only thing onPostExecute needs to do is pass the new items to your list adapter.

Also, do not use the same ArrayList as the one your adapter holds. If for some reason the adapter discovers that the data has changed without you having called notifyDataSetChanged(), it will probably crash (or at least display odd behaviors). Create a new ArrayList in your AsyncTask, then put this in your Adapter and call it from onPostExecute:

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


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!