【问题标题】:How can I create a ListView of bitmap and string updating progressively after OnCreate?如何在 OnCreate 之后逐步创建位图和字符串更新的 ListView?
【发布时间】:2012-01-12 04:22:21
【问题描述】:

我在主要活动上有一个ListView,它在左侧显示一个联系人图片,在每一行的右侧显示一个文本视图。一切正常,但问题是当应用程序启动时,当有很多消息时,用户必须等待大约 10 秒以上才能开始使用应用程序。

我试图做的是找到一种方法来逐步加载每一行,并避免等待每一行加载后才能开始使用应用程序。我试过AsyncTasksHandlersThreadsHashmaps.. 但我可以找到一种方法来管理这个任务。

我的活动是一个 ListActivity。

活动的列表视图使用带有参数的自定义适配器(this,smsarray,picturearray)。 smsarray 是一个ArrayList<String>,包含每条短信的字符串,picturearray 是一个ArrayList<Bitmap>,其中包含每条短信的位图格式的联系人图片。

我有一个方法getSMSData(),它在光标的帮助下获取短信字符串和位图,并将字符串放在 smsarray 上的索引 0 处,并将位图放在图片数组上的索引 0 处,用于启动时的每个联系人。

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;

}

}

感谢您的宝贵帮助。

【问题讨论】:

    标签: android listview android-widget


    【解决方案1】:

    您应该在MessageListAdaptergetView() 方法中进行,而不是解码所有位图并检索所有记录。在构造函数中传递 Cursor 并在适配器内部使用它。

    编辑:

    你可以将你的 getSMSData() 方法修改成这样:

    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 方法中使用此光标:

    public View getView(int position, View convertView, ViewGroup parent) {
        // ...
        vcursor.moveToPosition(position);
        // Now use this cursor to populate your convertView
        return convertView;
    }
    

    这样,您只需为用户可见的行加载数据。我希望这会有所帮助。

    如果您认为解码每条记录的联系人图片(每次调用 getView 方法)会减慢您的速度,您可以考虑将联系人图片保存在 Map 中(但不要一开始就通过迭代整个光标。这会让你回到第一格)并从那里加载它。 您也可以考虑使用AsyncTask 加载联系人图片,但由于您使用的是convertView,因此您需要小心。

    【讨论】:

    • 感谢您的回答; ) 我会努力的。你能指导我多一点我应该怎么做,它肯定会让我从这个负担中解脱出来,我的应用程序快完成了。谢谢。
    • @user1079001 我已将代码 sn-ps 添加到我的答案中。希望对您有所帮助。
    • 非常感谢您的帮助。它肯定应该以这种方式工作 =))
    【解决方案2】:

    我已经设法通过 CursorAdapter 的设置完成了所有工作。现在,我的适配器在我的 bindView 方法中直接使用光标获取联系人的号码、日期、消息和 id(如果存在),但是如果有 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.moveToFirst();在名称之前 = 联系人姓名光标......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-10
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    相关资源
    最近更新 更多