Android: reusing inline views in gridview [solution published]

I'm trying to reuse a framelayout that has an image and text inside it, but I don't think I'm doing it right. The code works, and the display is right, but the performance is very poor, and I think that is because I create a new ImageView and TextView every time the adapters return to the position position.

Can someone tell me how to reuse the built-in ImageView (called i) and TextView (called t) without creating new objects? I am very new to Java and this is my attempt to create an Android app.

public View getView(int position, View convertView, ViewGroup parent) { FrameLayout F; FrameLayout ImageBorder; FrameLayout TextBG; ImageView i; TextView t; if(convertView == null) { F = new FrameLayout(mContext); } else { F = (FrameLayout) convertView; } ImageBorder = new FrameLayout(F.getContext()); FrameLayout.LayoutParams params1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT,300,Gravity.BOTTOM); ImageBorder.setLayoutParams(params1); i = new ImageView(F.getContext()); TextBG = new FrameLayout(F.getContext()); t = new TextView(F.getContext()); F.setBackgroundColor(Color.BLACK); ImageBorder.setPadding(2, 2, 2, 2); ImageBorder.setBackgroundColor(Color.BLACK); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT,40,Gravity.BOTTOM); TextBG.setLayoutParams(params); TextBG.setBackgroundColor(Color.BLACK); TextBG.setAlpha(.6f); t.setLayoutParams(params); t.setGravity(Gravity.CENTER_VERTICAL); String pathToPhoto = FileList.get(position).toString(); String fileDescription = pathToPhoto.replaceAll("/mnt/external1/PaliPhotography/",""); fileDescription = fileDescription.replaceAll(".jpg",""); fileDescription = fileDescription.toUpperCase(); Bitmap bm = Cache.getCacheFile("thumb",pathToPhoto); if (bm == null) { ImageDownloader downloader = new ImageDownloader(i); downloader.execute("thumb", pathToPhoto, "400", "400"); } else { i.setImageBitmap(bm); i.setScaleType(ImageView.ScaleType.CENTER_CROP); t.setTextAppearance(getApplicationContext(), android.R.style.TextAppearance_Large); t.setText(" " + fileDescription); } ImageBorder.addView(i); ImageBorder.addView(TextBG); ImageBorder.addView(t); F.addView(ImageBorder); return F; } } 

Thank you in advance!

[EDIT]

--------------------------- DECISION ---------------- ------ -------------------------------

Here is the solution I implemented based on the feedback below! Thanks!

  public View getView(int position, View convertView, ViewGroup parent) { View ReturnThisView; ViewHolder holder; LayoutInflater inflater; holder = new ViewHolder(); if(convertView == null) { inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); ReturnThisView = inflater.inflate(R.layout.imagecell, null); ReturnThisView.setTag(holder); } else { ReturnThisView = convertView; } holder.TextDescription = (TextView) ReturnThisView.findViewById(R.id.PhotoDesc); holder.ImageThumbnail = (ImageView) ReturnThisView.findViewById(R.id.Thumbnail); String pathToPhoto = FileList.get(position).toString(); String fileDescription = pathToPhoto.replaceAll("/mnt/external1/PaliPhotography/",""); fileDescription = fileDescription.replaceAll(".jpg",""); fileDescription = fileDescription.toUpperCase(); Bitmap bm = Cache.getCacheFile("thumb",pathToPhoto); if (bm == null) { ImageDownloader downloader = new ImageDownloader(holder.ImageThumbnail); downloader.execute("thumb", pathToPhoto, "400", "400"); } else { holder.ImageThumbnail.setImageBitmap(bm); holder.ImageThumbnail.setScaleType(ImageView.ScaleType.CENTER_CROP); holder.TextDescription.setTextAppearance(getApplicationContext(), android.R.style.TextAppearance_Large); holder.TextDescription.setText(" " + fileDescription); } return ReturnThisView; } } static class ViewHolder { TextView TextDescription; ImageView ImageThumbnail; } 
+4
source share
2 answers
  • Instead of dynamically creating your view for each element, create an XML layout file, say row.xml.
  • If you find that convertView == null inflates a new line using inflater
  • Find your TextView and ImageView with View # findViewById
  • Create a Holder object to help keep links to recently found TextView and ImageView
  • Save the holder as a tag, so convertView.setTag(holder)
  • For an existing convertView object, find the Holder object by doing holder = convertView.getTag()
  • Set the text and image for these two saved objects, for example. holder.txt.setText("Foo")
  • Android adapter will do the rest as reusing bloated string instances

Perhaps even for your code, you can view the initialization and layout once and use the Holder template to avoid reinitializing the elements, but I think XML will give you a better experience.

+2
source

The solution you provided is inaccurate. ViewHolder is mainly used to prevent the view from bloating and calling findViewById () more than once.

In your code

  • You do not have to create a new holder every time! Instead, you should create a new viewer only when your convertView = null, and then save it in the ReturnThisView tag. If convertView is not null, then you must load this user that you saved earlier.

  • You avoided inflating the view, so well done (y), but you still use findViewById (). Use only findViewById () when convertView = null and you initialize the views in the view holder. If the convertView is not null, just use the stored views in the loaded viewHolder.

Here is an example:

  public View getView(int position, View convertView, ViewGroup parent) { View ReturnThisView; ViewHolder holder; LayoutInflater inflater; if(convertView == null) { inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); ReturnThisView = inflater.inflate(R.layout.imagecell, null); holder = new ViewHolder(); holder.TextDescription = (TextView) ReturnThisView.findViewById(R.id.PhotoDesc); holder.ImageThumbnail = (ImageView) ReturnThisView.findViewById(R.id.Thumbnail); ReturnThisView.setTag(holder); } else { ReturnThisView = convertView; holder = (ViewHolder)ReturnThisView.getTag(); } String pathToPhoto = FileList.get(position).toString(); String fileDescription = pathToPhoto.replaceAll("/mnt/external1/PaliPhotography/",""); fileDescription = fileDescription.replaceAll(".jpg",""); fileDescription = fileDescription.toUpperCase(); Bitmap bm = Cache.getCacheFile("thumb",pathToPhoto); if (bm == null) { ImageDownloader downloader = new ImageDownloader(holder.ImageThumbnail); downloader.execute("thumb", pathToPhoto, "400", "400"); } else { holder.ImageThumbnail.setImageBitmap(bm); holder.ImageThumbnail.setScaleType(ImageView.ScaleType.CENTER_CROP); holder.TextDescription.setTextAppearance(getApplicationContext(), android.R.style.TextAppearance_Large); holder.TextDescription.setText(" " + fileDescription); } return ReturnThisView; } } static class ViewHolder { TextView TextDescription; ImageView ImageThumbnail; 

}

I found out about this on the site .

0
source

Source: https://habr.com/ru/post/1388995/


All Articles