【问题标题】:Using Asynctask and listview with SQLite在 SQLite 中使用 Asynctask 和 listview
【发布时间】:2012-08-03 15:27:18
【问题描述】:

我使用 AsyncTask 查询 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();
        }

    }

【问题讨论】:

    标签: android sqlite android-listview android-asynctask nullpointerexception


    【解决方案1】:

    好吧,我不确定是否存在异常,但您似乎正在尝试在初始化之前将联系人添加到您的 contactx 数组列表中。您将其声明为实例变量,但直到 doInBackground() 方法结束时才对其进行初始化。那会抛出空指针...

    试着放线..

    contactx = new ArrayList<Contact>();
    

    在你的 onPreExecute() 方法中。

    【讨论】:

      【解决方案2】:
      lv = (ListView) findViewById(R.id.blacklist);
      

      我会看看这条线。您正试图从嵌套类中找到您的列表视图。尽管这将在 UI 线程上运行,但 AsyncTask 仍然不是一个活动。我相信您的空点是因为您的列表视图引用为空,因为 AsyncTask 的实例无法检索视图。

      【讨论】:

      • 这是真的..我不知道为什么你甚至能够编译这段代码,asynctask 不是一个视图..所以我很确定它没有 findViewById 方法..除非这个任务嵌套在一个活动中..
      • @Joel 它在活动内部。但是我认为无论如何您都不能以这种方式引用它。代码编译但未检索到 ListView。
      • 是的,这个任务嵌套在一个活动中 Joel @RyanGray 我按照你的建议做了它并且它有效,我更新了我的问题中的代码,模拟器中的代码现在工作得很好,但它仍然是无法在我的 android 设备中运行。当我运行它时只显示 ProgressDialog,可能是因为我使用大约 500 的联系人而不是我只使用 3 的模拟器。你能建议一种让它在设备上运行得更快的方法吗?感谢您的回复。
      • @RyanGray 他总是可以在该方法调用前加上 ActivityClassName.this 以确保正确的内容视图正在调用该函数。如果列表在当前内容视图中,则将检索该列表。
      • @mkounal 尝试在您的 while 循环中添加一条日志语句,这样每次您获得一个新联系人并存储它时......您可以观察发生的情况并查看当前计数。查看是否正在检索数据。
      【解决方案3】:
      1. 为什么适配器创建了两次(但只使用了一次),并且在 runInBackground 内部?是否应该仅在获取原始数据后在 onPostExecute 中创建?

      2. 有没有可能你没有很好地实现适配器?你看过谷歌的“listView 的世界”视频吗?请出示适配器的代码。

      3. 崩溃的异常是什么?

      【讨论】:

      • 您对 1 的看法是正确的。我将在星期一运行代码并检查结果并通知您。对于 3. 当我在移动设备上运行应用程序时,我没有看到任何异常,我只是看到 Dialog 运行了很长时间。我有没有可能在错误的地方使用 AsyncTask ?我在 onStart 方法中调用它。谢谢
      • 但您写道“应用程序崩溃”。你是说应用程序运行良好,但速度很慢?
      • 是的,它非常慢,当我需要 2 秒让模拟器检索联系人时,我需要 10 分钟来获取设备
      • hmmm ...优化技巧怎么样?是否可以只存储项目列表所需的最少数据,并根据需要加载额外的数据,因为它们是使用适配器显示的?例如,仅加载联系人的 ID 和姓名,然后在使用 getView 显示时加载(并存储)他们的号码。在任何情况下,请尝试测量每个降低应用程序速度的嫌疑人所花费的时间——获取 id、获取电话号码、获取姓名……这样我们就可以看到导致应用程序速度变慢的原因是什么缓慢。
      • 光标 cur = cr.query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);是否可以对光标的特定 ID 进行查询?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-14
      • 1970-01-01
      • 1970-01-01
      • 2011-12-05
      • 2013-02-09
      相关资源
      最近更新 更多