Android - ArrayAdapter:将TextView设置为SQLiteDatabase中的值

时间:2014-07-22 10:13:49

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

我想要完成的任务:

我想将ListView的每一行TextView动态设置(显示文本)到SQLite数据库中的值。

我尝试了什么:

getView()内,我通过findViewById()将所述TextView分配给全局变量。然后我将值position(来自getView()的参数)分配给我的全局变量mListRowPosition。在此之后,我通过new AttemptGetCustomerInfo().execute()执行我的AsyncTask子类。

我的AsyncTask子类从我的SQLiteDatabase获取DatabaseHelper。使用mListRowPosition,它会从customer_id数据集中的Service对象的方法getCustomerID()收到ArrayList<Service>

customer_id一起构建SQL查询以获取客户的短名称。查询后,它从Cursor获取字符串shortname。然后我setText(shortname)之前的全局TextView(在getView()内)。

问题:

这种作品&#39;在某些时候,但它似乎是如此缓慢,只有最后(几乎每次)都有一个值设置为其文本。有时它也会弄错。

在调试日志之后,我看到getView()被调用的速度比AsyncTask甚至完成要快得多(这很有意义,但它会破坏我解决问题的方法)。

同样有趣:我的调试日志告诉我getView()被更频繁地调用,然后ArrayList中有数据条目。如果有5个条目,它将调用getView()约15至20次。为什么呢?

背后的代码:

public class ServiceAdapter extends ArrayAdapter<Service> {

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // Get the data item for this position
        Service service = getItem(position);
        // Check if an existing view is being reused, otherwise inflate the view
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(
                    R.layout.listview_row, parent, false);
        }
        // Lookup view for data population
        TextView quantity = (TextView) convertView
                .findViewById(R.id.QUANTITY_CELL);
        TextView description = (TextView) convertView
                .findViewById(R.id.DESCRIPTION_CELL);
        Button delete = (Button) convertView.findViewById(R.id.BUTTON_DELETE);
        customerView = (TextView) convertView.findViewById(R.id.CUSTOMER_VIEW);
        mListRowPosition = position;
        Log.d("ServiceAdapter", "getView changed mListRowPositon to be "
                + String.valueOf(mListRowPosition));
        new AttemptGetCustomerInfo().execute();

        // Populate the data into the template view using the data object
        quantity.setText(String.valueOf(service.getQuantity()));
        description.setText(service.getDescription());

        // Set up the listener for the delete button.

        final int pos = position;
        delete.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                showDialog("deleteButton", pos);
            }
        });

        customerView.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                showDialog("customerView", pos);
            }
        });

        // Return the completed view to render on screen
        return convertView;
    }


class AttemptGetCustomerInfo extends AsyncTask<String, String, String> {
        String shortname = null;

        @Override
        protected String doInBackground(String... params) {

            DatabaseHelper db_helper = new DatabaseHelper(context);
            SQLiteDatabase db = db_helper.getReadableDatabase();

            Log.d("AttemptGetCustomerInfo",
                    "ListRowPos: " + String.valueOf(mListRowPosition));
            Log.d("AttemptGetCustomerInfo", "description of ListRowPos: "
                    + services.get(mListRowPosition).getDescription());
            int customer_id = services.get(mListRowPosition).getCustomerID();
            Log.d("AttemptGetCustomerInfo",
                    "customer id: " + String.valueOf(customer_id));
            Cursor c = db.rawQuery(
                    "SELECT " + CustomerEntry.COLUMN_NAME_SHORTNAME + " FROM "
                            + CustomerEntry.TABLE_NAME + " WHERE "
                            + CustomerEntry.COLUMN_NAME_CUSTOMER_ID + "="
                            + customer_id, null);
            Log.d("AttemptGetCustomerInfo",
                    "available cursor size" + String.valueOf(c.getCount()));
            if (c.getCount() == 0) {
                Log.d("AttemptGetCustomerInfo", "There are no Cursor entries!");
                return null;
            }
            c.moveToFirst();
            shortname = c
                    .getString(c
                            .getColumnIndexOrThrow(CustomerEntry.COLUMN_NAME_SHORTNAME));

            db.close();

            return null;
        }

        @Override
        protected void onPostExecute(String s) {
            if (shortname != null) {
                customerView.setText(shortname);
            }
        }
    }

其他信息:

我没有粘贴所有代码,并且在上面的代码中发生了很多代码引用,其中也没有代码。我希望通过方法名称可以理解我的方法未显示的功能。

1 个答案:

答案 0 :(得分:2)

所以,让我们开始。

如果您想在Listview中显示数据库中的信息,我强烈建议您使用CursorAdapter代替ArrayAdapter,它的工作速度可能比现在快得多。

关于getView()调用,因为Android绘制列表视图的方式,Android首次调用getView()几次以便正确显示内容,如果您更改了例如ListView 1}}从match_parentwrap_content的高度或反之,您会注意到getView()方法会被调用不同的次数。


现在关于您的代码,您没有正确编写getView()方法。在第一部分if (convertView == null)内,您应该使用ViewHolder pattern定义您的观点,这将提高您的效果。

我在这里发现的另一个问题是,每次调用AsyncTask方法时都会启动getView(),这会导致ListView滚动出现问题,因为它会阻止顺利(例如,在平板电脑中,你将一个接一个地运行40或50个asynctask,这是一个繁重的工作量。)

如果您想保留当前的代码,我强烈建议您不要这样做,您需要一种方法来控制当前行是否已经执行了AsyncTask代码,以便不重复该工作。

希望有所帮助