Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it better to use multiple SpanObjects or multiple TextViews in Android?

I have a ListView that has a TextView and in each TextView several items, each with a brief description. In order to apply different styles to the items and description I am using multiples span objects: ClickableSpan, ForegroundColorSpan, BackgroundColorSpan, AbsoluteSizeSpan and StyleSpan.

On average the ListView has 10 TextViews, and each TextView has 10 pairs of item/description and each pair uses around 6 SpanObjects so a total of ~600 SpanObjects per ListView. And when the user clicks one of the items the ListView is cleared and redraw again generating another set of 600 SpanObjects.

So I am wondering if it would be a better idea to create one TextView for each item and each description and format it through XML rather than styling the TextViews with span, this way there would be around 200 TextViews and no SpanObjects.

As a note, I did not start with this approach because the hierarchy tree of views was going to be more complex and TextViews are more expensive to create that the SpanObjects but now that I see the number of SpanObjects I am creating I am not sure what is better. I am also thinking to start writing a recycling mechanism but not sure if it is worth or this should not be a problem for Android GC.

like image 700
garibay Avatar asked Apr 11 '12 16:04

garibay


1 Answers

I know its been a couple years since you've asked this question, and I hope you've found an answer by now, but I thought I'd answer your question anyhow.

The amount of TextViews and SpanObjects you have are incredibly expensive for any android device, and loading them each time can not only cause lag, but possibly a OOM-related crash (out of memory).

The approach to solving this is using a RecyclerView and CardView. First, write your RecyclerView adapter. Within this class, write a static class that loads all of the TextViews and other items within each card (a card is essentially a list item). This way, all of your items are loaded on OnCreate, and are not continuously generated. This is especially helpful if you're using fragments. This link may be of use to you: http://www.binpress.com/tutorial/android-l-recyclerview-and-cardview-tutorial/156

Here is an example of a RecyclerView adapter class with the static class:

public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactViewHolder> {

    private List<ContactInfo> contactList;

    public ContactAdapter(List<ContactInfo> contactList) {
            this.contactList = contactList;
    }

    @Override
    public int getItemCount() {
          return contactList.size();
    }

    @Override
    public void onBindViewHolder(ContactViewHolder contactViewHolder, int i) {
        ContactInfo ci = contactList.get(i);
        contactViewHolder.vName.setText(ci.name);
        contactViewHolder.vSurname.setText(ci.surname);
        contactViewHolder.vEmail.setText(ci.email);
        contactViewHolder.vTitle.setText(ci.name + " " + ci.surname);
   }

   @Override
   public ContactViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View itemView = LayoutInflater.
                    from(viewGroup.getContext()).
                    inflate(R.layout.card_layout, viewGroup, false);

        return new ContactViewHolder(itemView);
   }


   //Static class that loads all card item components

  public static class ContactViewHolder extends RecyclerView.ViewHolder {
     protected TextView vName;
     protected TextView vSurname;
     protected TextView vEmail;
     protected TextView vTitle;

     public ContactViewHolder(View v) {
          super(v);
          vName =  (TextView) v.findViewById(R.id.txtName);
          vSurname = (TextView)  v.findViewById(R.id.txtSurname);
          vEmail = (TextView)  v.findViewById(R.id.txtEmail);
          vTitle = (TextView) v.findViewById(R.id.title);
      }
 }
}
like image 176
Jason Cromer Avatar answered Oct 23 '22 16:10

Jason Cromer