如何在OnCreate之后逐步创建位图的ListView和字符串更新?

时间:2011-12-03 14:03:15

标签: android listview android-widget

主活动上有ListView,左侧显示联系人图片,每行显示右侧的文本视图。一切都像它应该的那样工作,但问题是当应用程序启动时,并且当有很多消息时,用户必须等待大约10秒以上才能开始使用该应用程序。

我尝试做的是找到一种逐步加载每一行的方法,并避免等待加载每一行以开始使用该应用程序。我尝试了AsyncTasksHandlersThreadsHashmaps ..但我可以找到管理此任务的方法。

我的活动是ListActivity。

活动的列表视图使用带参数的自定义适配器(this,smsarray,picturearray)。 smsarray是包含每个短信的字符串ArrayList<String>picturearrayArrayList<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;

}

}

感谢您的宝贵帮助。

2 个答案:

答案 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?我也尝试使用适配器的光标,但它也给了我一个例外...我会尝试不同的方法,但了解它失败的原因应该帮助我和其他读者提高他们的知识,如果你有答案; )