Android - ArrayAdapter:将 TextView 设置为 SQLiteDatabase 中的值
Posted
技术标签:
【中文标题】Android - ArrayAdapter:将 TextView 设置为 SQLiteDatabase 中的值【英文标题】:Android - ArrayAdapter: set TextView to value from SQLiteDatabase 【发布时间】:2014-09-13 02:36:42 【问题描述】:我想要完成的事情:
我希望将 ListView 的每行一个 TextView 动态设置(其显示文本)为 SQLite 数据库中的值。
我尝试了什么:
在getView()
中,我通过findViewById()
将上述TextView 分配给了一个全局变量。然后我将值position
(来自getView()
的参数)分配给我的全局变量mListRowPosition
。之后,我通过new AttemptGetCustomerInfo().execute()
执行我的 AsyncTask 子类。
我的 AsyncTask 子类从我的 DatabaseHelper
获取 SQLiteDatabase
。使用mListRowPosition
,它从ArrayList<Service>
数据集中的Service 对象的getCustomerID()
方法接收customer_id
。
与customer_id
一起,它构建了一个SQL 查询来获取客户的简称。查询后,从 Cursor 中获取字符串shortname
。然后我 setText(shortname)
之前的全局 TextView(在 getView()
内部)。
这样做的问题:
这种“工作”在某些时候,但它似乎太慢了,以至于只有最后一个(几乎每次)都有一个值设置为它的文本。有时它也会出错。
在调试日志记录之后,我看到调用 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】:那么,让我们开始吧。
如果您想在Listview
中显示数据库中的信息,我强烈建议您使用CursorAdapter
而不是ArrayAdapter
,它的运行速度可能比现在快得多。
关于getView()
调用,这是由于android 绘制列表视图的方式而发生的,Android 第一次会调用getView()
多次以正确显示事物,例如,如果您将ListView
的高度从@ 更改为987654328@ 到 wrap_content
或反之亦然,您会注意到您的 getView()
方法将被调用不同的次数。
现在关于您的代码,您没有正确编程您的getView()
方法。在第一部分if (convertView == null)
中,您应该使用ViewHolder pattern 定义您的视图,这将提高您的性能。
我在这里发现的另一个问题是,每次调用 getView()
方法时,您都会启动您的 AsyncTask
,这将导致您的 ListView
滚动出现问题,因为它会阻止顺利进行(在平板电脑中例如,您将一个接一个地运行 40 或 50 个异步任务,这是一个繁重的工作量)。
如果您想保留当前代码(我强烈建议您不要这样做),您将需要一种方法来控制当前行是否已执行您的 AsyncTask
代码,以免重复该工作。
希望对你有帮助
【讨论】:
那么您如何看待整体问题的解决方案?如果我使用 CursorAdapter 会解决我的问题吗? 你会有相当的进步 感谢您的补充。我应用了 ViewHolder 模式并保存了 LayoutInflater 参考以供将来访问。这似乎是一些更好的性能,但它并不能解决一些 TextViews 只是空的而另一个被填充(使用错误的文本)的问题。我很高兴更改我的代码,但除了您告诉我的更改之外,我想不出有什么不同。我需要为每一行运行 AsyncTask。我认为这将是最好的方法,但似乎并不完全如此。您在代码形式上是否有进一步的改进(如果可能)? 如果您事先为您需要的每一行运行该查询并将其与您的Service
对象一起发送怎么办?那会更快
还有一个改进:运行查询后总是关闭游标!否则,会产生内存泄漏。以上是关于Android - ArrayAdapter:将 TextView 设置为 SQLiteDatabase 中的值的主要内容,如果未能解决你的问题,请参考以下文章
Android View 不会通过滑动手势滚动,也不会滚动。将 ListView 与 ArrayAdapter 一起使用
Android:使用 ArrayAdapter 在 ListView 中替换颜色 [重复]