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

时间:2014-02-02 06:59:29

标签: android listview android-asynctask

我理解这个错误的含义。我在stackoverflow.com上发现了许多类似的问题,我试图实现建议的答案,但我仍然收到此错误。我想要做的是使用php web服务我从mysql数据库服务器中提取数据并尝试使用AsyncTask在listview中显示它,如下所示:

class LoadAllProducts extends AsyncTask<String, String, ArrayList<HashMap<String, String>>> 
{
    ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
    protected ArrayList<HashMap<String, String>> doInBackground(String... args)
    {
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        JSONObject json = jParser.makeHttpRequest(url_all_products, "GET", params);

        Log.d("All Products: ", json.toString());
        try {

                JSONArray  files = json.getJSONArray(TAG_FILES);
                for(int i=0;i<files.length();i++)
                {                     
                    HashMap<String, String> map = new HashMap<String, String>();    
                    JSONObject e = files.getJSONObject(i);


                    String file_name = e.getString(TAG_FILE_NAME);
                    String sender = e.getString(TAG_SENDER);
                    String subject = e.getString(TAG_SUBJECT);


                    map.put(TAG_SENDER, sender);
                    map.put(TAG_SUBJECT, subject);

                    mylist.add(map);            
                } 


        } catch (JSONException e) 
        {
            e.printStackTrace();
            Log.e("log_tag", "Error parsing data "+e.toString());
        }

        return mylist;

    }

许多答案都建议,所有处理都应该在doInBackground函数中完成。现在,下面是在ListView中显示此arraylist的代码

 protected void onPostExecute(String file_url) 
    {

        pDialog.dismiss();

        runOnUiThread(new Runnable() 
        {
            public void run() 
            {
                String[] from = { TAG_SENDER, TAG_SUBJECT };
                int[] to = { android.R.id.text1, android.R.id.text2 };


                ListAdapter adapter = new SimpleAdapter(AllProductsActivity.this, mylist,
                        android.R.layout.simple_list_item_2, from , to);
                      setListAdapter(adapter);

            }
        });

    }

请帮助首先我是android的初学者,我不知道如何解决这个问题。请检查我的代码并让我知道问题。

2 个答案:

答案 0 :(得分:8)

如果你的主线程做了这么多工作,就会出现这种错误。基本上跳帧会在我们在模拟器中测试我们的应用程序时发生,因为它已经很慢并且无法处理像设备这样的巨大操作。

我在你的代码中看到了一个简单的问题。我们知道onPostExecute()在MainThread上运行,但你仍然在onPostExecute()中使用runOnUiThread(new Runnable()

你doinbackground方法返回一个ArrayList,但你的onpostexecute持有一个字符串..

将其更改为我的onPostExecute'参数,即您在适配器中使用的ArrayList(mylist)。

修改

  class LoadAllProducts extends AsyncTask<String, String, ArrayList<HashMap<String, String>>> {

    ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
    protected ArrayList<HashMap<String, String>> doInBackground(String... args){
    HttpClient client = new DefaultHttpClient();
    HttpGet getData = new HttpGet("your_url");
    HttpResponse response = client.execute(getData);
    BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
    String data = "";

    while((data = br.readLine()) != null){
    JsonArray arr = new JsonArray(data);
       for(int i=0;i<arr.length();i++)
            {                     
                HashMap<String, String> map = new HashMap<String, String>();    
                JSONObject e = arr.getJSONObject(i);

                String file_name = e.getString(TAG_FILE_NAME);
                String sender = e.getString(TAG_SENDER);
                String subject = e.getString(TAG_SUBJECT);


                map.put(TAG_SENDER, sender);
                map.put(TAG_SUBJECT, subject);

                mylist.add(map);            

    }

    return mylist;

}

 protected void onPostExecute(ArrayList<HashMap<String, String>> mylist) {
            String[] from = { TAG_SENDER, TAG_SUBJECT };
            int[] to = { android.R.id.text1, android.R.id.text2 };


            ListAdapter adapter = new SimpleAdapter(AllProductsActivity.this, mylist,
                    android.R.layout.simple_list_item_2, from , to);
                  setListAdapter(adapter);

              pDialog.dismiss();

        }

答案 1 :(得分:2)

对不起,这不是一个超级明智的答案,但我有2条建议。首先,消除runOnUiThread调用,因为onPostExecute已经在ui线程上运行(这是方法的要点)。这对任何跳帧都没有帮助,但至少你可以摆脱一些不需要的代码。

其次,在ListAdapter中创建doInBackground。我怀疑它会有多大的不同,但你可能会尽可能多地从UI线程中获取。因此,您将使用AsyncTask<String, String, ArrayList<HashMap<String, String>>>而不是AsyncTask<String, String, ListAdapter>。这只会在onPostExecutepDialog.dismisssetListAdapter中留下2个方法调用。你不能比这更有效率。如果它仍然跳过帧,我会责怪调试器并继续前进。