我想要完成的任务:
我想将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);
}
}
}
其他信息:
我没有粘贴所有代码,并且在上面的代码中发生了很多代码引用,其中也没有代码。我希望通过方法名称可以理解我的方法未显示的功能。
答案 0 :(得分:2)
所以,让我们开始。
如果您想在Listview
中显示数据库中的信息,我强烈建议您使用CursorAdapter
代替ArrayAdapter
,它的工作速度可能比现在快得多。
关于getView()
调用,因为Android绘制列表视图的方式,Android首次调用getView()
几次以便正确显示内容,如果您更改了例如ListView
1}}从match_parent
到wrap_content
的高度或反之,您会注意到getView()
方法会被调用不同的次数。
现在关于您的代码,您没有正确编写getView()
方法。在第一部分if (convertView == null)
内,您应该使用ViewHolder pattern定义您的观点,这将提高您的效果。
我在这里发现的另一个问题是,每次调用AsyncTask
方法时都会启动getView()
,这会导致ListView
滚动出现问题,因为它会阻止顺利(例如,在平板电脑中,你将一个接一个地运行40或50个asynctask,这是一个繁重的工作量。)
如果您想保留当前的代码,我强烈建议您不要这样做,您需要一种方法来控制当前行是否已经执行了AsyncTask
代码,以便不重复该工作。
希望有所帮助