主活动上有ListView
,左侧显示联系人图片,每行显示右侧的文本视图。一切都像它应该的那样工作,但问题是当应用程序启动时,并且当有很多消息时,用户必须等待大约10秒以上才能开始使用该应用程序。
我尝试做的是找到一种逐步加载每一行的方法,并避免等待加载每一行以开始使用该应用程序。我尝试了AsyncTasks
,Handlers
,Threads
,Hashmaps
..但我可以找到管理此任务的方法。
我的活动是ListActivity。
活动的列表视图使用带参数的自定义适配器(this,smsarray,picturearray)。
smsarray
是包含每个短信的字符串ArrayList<String>
,picturearray
是ArrayList<Bitmap>
,其中包含每个短信的位图格式的联系人图片。
我有一个方法getSMSData()
,它在游标的帮助下获取sms字符串和位图,并将字符串放在smsarray上的索引0处,以及在picturearray上的索引0处的位图,用于启动时的每个联系人。 / p>
public class MessageList extends ListActivity {
static List<String> smsarray; static List<Bitmap> picturearray;
static MessageListAdapter smsadapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
smsarray = new ArrayList<String>();
picturearray = new ArrayList<Bitmap>();
getSMSData();
smsadapter = new MessageListAdapter(this,smsarray,picturearray);
getListView().setAdapter(smsadapter);
}
public void getSMSData() {
Bitmap defaultbitmap = BitmapFactory.decodeResource(getResources(), R.drawable.default_contact_picture);
Bitmap contactbitmap;
Cursor cursor = getContentResolver().query(Uri.parse("content://sms/inbox"),new String [] {"person","address","body","date"} , null, null,"date ASC");
String[] displayname = new String[]{ContactsContract.Contacts.DISPLAY_NAME};
String name;
String person;
String address;
String date;
String body;
int id; Cursor contactcursor;
while (cursor.moveToNext()) {
person = cursor.getString(cursor.getColumnIndex("person"));
address = cursor.getString(cursor.getColumnIndex("address"));
date = cursor.getString(cursor.getColumnIndex("date"));
body = cursor.getString(cursor.getColumnIndex("body"));
if (person != null){
contactcursor = getContentResolver().query(Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, person),displayname, null, null, null);
contactcursor.moveToFirst();
name = contactcursor.getString(0);
id = Integer.parseInt(person);
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(), ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id));
contactbitmap = null;
if (input == null) {
contactbitmap = defaultbitmap;
} else {
contactbitmap = BitmapFactory.decodeStream(input);
}
if (contactbitmap != null){
picturearray.add(0,contactbitmap);
}else {
picturearray.add(0,defaultbitmap);
}
smsarray.add(0,getResources().getString(R.string.From) +" "+name+" "+"\n"+getResources().getString(R.string.Number)+" "+address+" " +"\n"+getResources().getString(R.string.At) +" "+date+"\n"+getResources().getString(R.string.Message)+" "+body);
}
if (person == null) {
picturearray.add(0,defaultbitmap);
smsarray.add(0,getResources().getString(R.string.From) +" "+getResources().getString(R.string.Unknown)+" "+"\n"+getResources().getString(R.string.Number)+" "+address+" " +"\n"+getResources().getString(R.string.At) +" "+date+"\n"+getResources().getString(R.string.Message)+" "+body);
}
}
}
}
public class MessageListAdapter extends ArrayAdapter <String> {
final Context vcontext;
final List<String> varray;
final List<Bitmap> vpicture;
final LayoutInflater layoutinflater;
public MessageListAdapter (Context context,List<String> smsarray, List<Bitmap> picturearray) {
super(context, 0);
vcontext = context;
varray = smsarray;
vpicture = picturearray;
this.layoutinflater = LayoutInflater.from(context);
}
public int getCountpicture() {
return vpicture.size();
}
public Bitmap getItempicture(int position) {
return vpicture.get(position);
}
public long getItemIdpicture(int position) {
return position;
}
public int getCount() {
return varray.size();
}
public String getItem(int position) {
return varray.get(position);
}
public long getItemId(int position) {
return position;
}
public class ViewHolder {
TextView messagetext;
ImageView image;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null){
convertView = layoutinflater.inflate(R.layout.listitem, null);
holder = new ViewHolder ();
holder.messagetext = (TextView) convertView.findViewById(R.id.messagetext);
holder.image = (ImageView) convertView.findViewById(R.id.contactimage);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.image.setImageBitmap(vpicture.get(position));
holder.image.setPadding(2, 1, 0, 0);
holder.messagetext.setText(varray.get(position));
holder.messagetext.setPadding(10, -1, 10, 5);
return convertView;
}
}
感谢您的宝贵帮助。
答案 0 :(得分:1)
您应该使用getView()
的{{1}}方法进行解码,而不是解码所有位图并最初检索所有记录。在构造函数中传递Cursor并从适配器内部使用它。
编辑:
您可以将getSMSData()方法修改为以下内容:
MessageListAdapter
并在public Cursor getSMSData() {
Cursor cursor = getContentResolver().query(Uri.parse("content://sms/inbox"),new String [] {"person","address","body","date"} , null, null,"date ASC");
return cursor;
}
中使用此光标创建onCreate
,如下所示:
MessageListAdapter
修改Cursor cursor = getSMSData();
smsadapter = new MessageListAdapter(this, cursor);
构造函数以接收并保存光标:
MessageListAdapter
然后在适配器的public MessageListAdapter (Context context,Cursor cursor) {
super(context, 0);
vcontext = context;
vcursor = cursor;
this.layoutinflater = LayoutInflater.from(context); // alternately, you could use the View.inflate() method
}
方法中使用此光标:
getView
这样,您只需加载用户可见的行的数据。我希望有所帮助。
如果您认为解码每条记录的联系人图片(每次调用getView方法)都会降低您的速度,您可以考虑将联系人图片保存在Map中(但不要通过迭代迭代来解码所有图片)整个光标。那会让你回到正方形)并从那里加载它。
您还可以考虑使用public View getView(int position, View convertView, ViewGroup parent) {
// ...
vcursor.moveToPosition(position);
// Now use this cursor to populate your convertView
return convertView;
}
加载联系人图片,但由于您使用AsyncTask
,因此需要小心。
答案 1 :(得分:0)
我已经设法通过设置CursorAdapter来完成所有工作。现在我的适配器直接用光标获取数字,日期,消息和联系人的id(如果存在),在我的bindView方法中,但如果有id,我无法弄清楚如何设置联系人的姓名。我认为这会奏效:
public void bindView(View view, Context context, Cursor cursor) {
String contact = cursor.getString(cursor.getColumnIndex("person"));
TextView contacttext = (TextView) view.findViewById(R.id.from);
String name = "";
if(contact == null) {
name = "unknown";
}
if(contact != null) {
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI,contact);
Cursor contactnamecursor = getContentResolver().query(uri, new String[]{ContactsContract.Contacts.DISPLAY_NAME}, null, null, null);
name = contactnamecursor.getString(contactnamecursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
}
contacttext.setText(name);
}
但似乎我不能在我的CursorAdapter中使用新光标。当我滚动列表时它会给我一个例外(当它到达一行时它应该显示联系人的名字,通常)为什么我不能使用我的新contactnamecursor?我也尝试使用适配器的光标,但它也给了我一个例外...我会尝试不同的方法,但了解它失败的原因应该帮助我和其他读者提高他们的知识,如果你有答案; )