0

我使用AsyncTask來查詢SQLite數據庫 - 聯繫人。使用Asynctask和ListView與SQLite

當我在android模擬器上運行該代碼時,它工作正常(可能是因爲我沒有添加聯繫人),但是當我在我的手機上運行它(它有大約500個聯繫人)時,應用程序運行緩慢。

任何幫助,將不勝感激。謝謝。

該代碼如下。

 private class loadMoreListView extends AsyncTask<Void, Void, Void> { 

      ArrayList<Contact> contactsx = new ArrayList<Contact>(); 
      @Override 
      protected void onPreExecute() { 
       pDialog = new ProgressDialog(MainActivity.this); 
       pDialog.setMessage("Please wait.."); 
       pDialog.setIndeterminate(true); 
       pDialog.setCancelable(false); 
       pDialog.show(); 
       lv = (ListView) findViewById(R.id.blacklist); 

      } 

      @Override 
      protected void onPostExecute(Void unused) { 
       // closing progress dialog 

       lv.setAdapter(adapter); 

       pDialog.dismiss(); 
      } 

      @Override 
      protected Void doInBackground(Void... params) { 
       // TODO Auto-generated method stub 


       ArrayList<Contact> contactItemsTemp = new ArrayList<Contact>(); 

       adapter = new EfficientAdapter(MainActivity.this, contactItems); 

       DatabaseHandler db = new DatabaseHandler(MainActivity.this); 
       String name = ""; 
       String id = ""; 
       String phoneNumber = ""; 
       // Cursor cursor = null; 

       List<Integer> mycontactID; 
       mycontactID = db.getAllIDs(); 

       Iterator value = mycontactID.iterator(); 

       while (value.hasNext()) { 
        int mg=(Integer)value.next(); 

        ContentResolver cr = getContentResolver(); 
        Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, 
          null, null, null); 
       // Log.d("edw",Integer.toString(mg)); 
        if (cur.getCount() > 0) { 

         while (cur.moveToNext()) { 
          id = cur.getString(cur 
            .getColumnIndex(ContactsContract.Contacts._ID)); 
          if (id.equals((mg))) 
           ; 
          { 
           name = cur 
             .getString(cur 
               .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); 
           if (Integer 
             .parseInt(cur.getString(cur 
               .getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) { 

            Cursor pCur = cr 
              .query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
                null, 
                ContactsContract.CommonDataKinds.Phone.CONTACT_ID 
                  + " = ?", 
                new String[] { id }, null); 
            while (pCur.moveToNext()) { 
             Log.d("number", 
               pCur.getString(pCur 
                 .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))); 
             // Do something with phones 
             phoneNumber = pCur 
               .getString(pCur 
                 .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 
            } 
            contactItemsTemp.add(new Contact(Integer 
              .parseInt(id), name, phoneNumber)); 
            pCur.close(); 

            Log.d("Name", name); 
           } 
          } 
         } 

         cur.close(); 
        } 

       } 
       // na kanw to temp contactItems 

       List<Integer> messagesx; 
       messagesx = db.getAllIDs(); 
       String namex = ""; 
       String phonex = ""; 
       for (Integer mg : messagesx) { 
        for (int i = 0; i < contactItemsTemp.size(); i++) { 
         if (contactItemsTemp.get(i).getID() == mg) { 
          namex = contactItemsTemp.get(i).getContactName(); 
          phonex = contactItemsTemp.get(i).getPhoneNumber(); 
         } 
        } 

        contactsx.add(new Contact(mg, namex, phonex)); 
       } 

       adapter = new EfficientAdapter(MainActivity.this, contactsx); 


       db.close(); 


       return null; 
      } 
     } 



public static class EfficientAdapter extends ArrayAdapter<Contact> 
      implements Filterable { 
     private LayoutInflater mInflater; 
     // private Bitmap mIcon1; 
     private final Context context; 
     private final ArrayList<Contact> values; 

     public EfficientAdapter(Context context, ArrayList<Contact> values) { 
      // Cache the LayoutInflate to avoid asking for a new one each time. 
      super(context, R.layout.myobject, values); 
      mInflater = LayoutInflater.from(context); 
      this.context = context; 
      this.values = values; 
     } 

     /** 
     * Make a view to hold each row. 
     * 
     * @see android.widget.ListAdapter#getView1(int, android.view.View, 
     *  android.view.ViewGroup) 
     */ 
     @Override 
     public View getView(final int position, View convertView, 
       ViewGroup parent) { 

      ViewHolder holder; 

      if (convertView == null) { 
       convertView = mInflater.inflate(R.layout.myobject, null); 

       holder = new ViewHolder(); 
       holder.contact = (TextView) convertView 
         .findViewById(R.id.contact); 
       holder.ph_num = (TextView) convertView 
         .findViewById(R.id.ph_num); 

       convertView.setTag(holder); 
      } 

      else { 
       // Get the ViewHolder back to get fast access to the TextView 
       // and the ImageView. 
       holder = (ViewHolder) convertView.getTag(); 
      } 

      convertView.setOnLongClickListener(new View.OnLongClickListener() { 
       private int pos = position; 

       @Override 
       public boolean onLongClick(View v) { 
        // TODO Auto-generated method stub 

        // prepare the alert box 
        AlertDialog.Builder alertbox = null; 
        alertbox = new AlertDialog.Builder(context); 
        // set the message to display 
        alertbox.setMessage("Are you sure you want to remove the contact from the blacklist?"); 
        // add a neutral button to the alert box and assign a click 
        // listener 
        alertbox.setNeutralButton("OK", 
          new DialogInterface.OnClickListener() { 

           @Override 
           public void onClick(DialogInterface dialog, 
             int which) { 
            // TODO Auto-generated method stub 
            Toast.makeText(context, 
              "Ok button pressed " + pos, 
              Toast.LENGTH_SHORT).show(); 

            DatabaseHandler db = new DatabaseHandler(
              context); 
            db.deleteContact(values.get(position) 
              .getID()); 
            db.close(); 
           } 
          }); 

        alertbox.setNegativeButton("Cancel", 
          new DialogInterface.OnClickListener() { 

           @Override 
           public void onClick(DialogInterface dialog, 
             int which) { 
            // TODO Auto-generated method stub 
            Toast.makeText(context, 
              "Cancel button pressed " + pos, 
              Toast.LENGTH_SHORT).show(); 
           } 
          }); 

        alertbox.show(); 
        return true; 
       } 
      }); 

      convertView.setOnClickListener(new OnClickListener() { 
       private int pos = position; 

       @Override 
       public void onClick(View v) { 
        // Toast.makeText(context, "Click-" + pos, 
        // Toast.LENGTH_SHORT) 
        // .show(); 
       } 
      }); 

      holder.contact.setText(getItem(position).getContactName()); 
      holder.ph_num.setText(getItem(position).getPhoneNumber()); 

      return convertView; 

     } 

     static class ViewHolder { 
      TextView contact; 
      TextView ph_num; 

     } 

     @Override 
     public int getCount() { 
      // TODO Auto-generated method stub 
      return values.size(); 
     } 

     @Override 
     public Contact getItem(int position) { 
      // TODO Auto-generated method stub 
      return values.get(position); 
     } 

     @Override 
     public long getItemId(int position) { 
      // TODO Auto-generated method stub 
      return 0; 
     } 

     @Override 
     public Filter getFilter() { 
      // TODO Auto-generated method stub 
      return null; 
     } 

     public void add(Contact con) { 
      values.add(con); 

      notifyDataSetChanged(); 
     } 

     public void replace(int index, Contact con) { 
      values.set(index, con); 
      notifyDataSetChanged(); 
     } 

     public void clear() { 
      values.clear(); 
      notifyDataSetChanged(); 
     } 

     public void remove(Contact con) { 
      values.remove(con); 
      notifyDataSetChanged(); 
     } 

    } 

回答

0

好了,我不知道的例外,但它好像你正試圖接觸你初始化之前添加到您的contactx數組列表。您將其聲明爲實例變量,但不要在doInBackground()方法的末尾初始化它。這將引發空指針...

嘗試將行..

contactx = new ArrayList<Contact>(); 

在你onPreExecute()方法。

0
lv = (ListView) findViewById(R.id.blacklist); 

我會看看這一行。你正試圖從嵌套類中找到你的列表視圖。儘管這將在UI線程上運行,但AsyncTask仍然不是一項活動。我相信你的空點是因爲AsyncTask的一個實例無法檢索視圖,因此你的listview引用爲null。

+0

這是真的。我不知道爲什麼你甚至可以編譯這段代碼,一個的AsyncTask是不是一個視圖..所以我敢肯定它沒有一個findViewById方法..除非這任務嵌套在一個活動中.. – Joel 2012-08-03 17:09:33

+0

@Joel它是一個活動的內部。但我認爲你無論如何都不能以這種方式引用它。代碼編譯但ListView不被檢索。 – 2012-08-03 18:59:48

+0

是的,這個任務是嵌套在一個活動Joel @RyanGray我做了它像你建議和它的工作,我更新了我的問題中的代碼,在模擬器中的代碼現在工作得很好,但它仍然不能運行在我的機器人內部設備。當我運行它時,只顯示ProgressDialog,可能是因爲我使用的是大約500的接觸點,而不是我只使用3的模擬器。 您能否提出一種使其在設備上更快運行的方法? 謝謝你的回覆。 – mkounal 2012-08-03 23:20:58

0
  1. 爲什麼適配器創建了兩次(但只用過一次),並且在runInBackground中?是否應該在獲取原始數據之後創建onPostExecute?

  2. 是否有可能您沒有很好地實現適配器?你有沒有看過谷歌的「listView世界」視頻?請顯示適配器的代碼。

  3. 什麼是崩潰的例外?

+0

您對我來說是正確的。我將在星期一運行代碼並檢查結果和信息。 對於3.我在移動設備上運行應用程序時看不到任何異常,我只看到對話框運行了很長時間。 有沒有機會在某處錯誤地使用AsyncTask?我在onStart方法中調用它。 謝謝 – mkounal 2012-08-04 16:39:31

+0

但你寫到「應用程序崩潰」。你說應用程序工作正常,但它只是慢? – 2012-08-04 17:03:58

+0

是的這是非常慢,當我需要2秒的模擬器檢索聯繫人,我需要10分鐘的設備 – mkounal 2012-08-04 17:45:53