listview优化(中)

1,对Imageview使用setTag()方法来解决图片错位问题,这个Tag中设置的是图片的url,然后在加载的时候取得这个url和要加载那position中的url对比,如果不相同就加载,相同就是复用以前的就不加载了

2,对于要加载的图片资源,先在内存缓存中找(原始的方法是使用SoftRefrence,最新的方法是使用android提供的Lrucache),如果找不到,则在本地缓存(可以使用DiskLrucache类)中找(也就是读取原先下载过的本地图片),还找不到,就开启异步线程去下载图片,下载以后,保存在本地,内存缓存也保留一份引用

3,在为imagview装载图片时,先测量需要的图片大小,按比例缩放

4,使用一个Map保存异步线程的引用,key->value为url->AsyncTask,这样可以避免已经开启了线程去加载图片,但是还没有加载完时,又重复开启线程去加载图片的情况

5,在快速滑动的时候不加载图片,取消所有图片加载线程,一旦停下来,继续可见图片的加载线程

下面都是我摘取的网上的一些例子,我分别介绍它们来说明上述的优化思路

第一个例子:

[java] view
plain
copy

  1. public class MemoryCache {  
  2.   
  3.     private static final String TAG = "MemoryCache";  
  4.     // 放入缓存时是个同步操作  
  5.     // LinkedHashMap构造方法的最后一个参数true代表这个map里的元素将按照最近使用次数由少到多排列,即LRU  
  6.     // 这样的好处是如果要将缓存中的元素替换,则先遍历出最近最少使用的元素来替换以提高效率  
  7.     private Map<String, Bitmap> cache = Collections  
  8.             .synchronizedMap(new LinkedHashMap<String, Bitmap>(10, 1.5f, true));  
  9.     // 缓存中图片所占用的字节,初始0,将通过此变量严格控制缓存所占用的堆内存  
  10.     private long size = 0;// current allocated size  
  11.     // 缓存只能占用的最大堆内存  
  12.     private long limit = 1000000;// max memory in bytes  
  13.   
  14.     public MemoryCache() {  
  15.         // use 25% of available heap size  
  16.         setLimit(Runtime.getRuntime().maxMemory() / 4);  
  17.     }  
  18.   
  19.     public void setLimit(long new_limit) {   
  20.         limit = new_limit;  
  21.         Log.i(TAG, "MemoryCache will use up to " + limit / 1024. / 1024. + "MB");  
  22.     }  
  23.   
  24.     public Bitmap get(String id) {  
  25.         try {  
  26.             if (!cache.containsKey(id))  
  27.                 return null;  
  28.             return cache.get(id);  
  29.         } catch (NullPointerException ex) {  
  30.             return null;  
  31.         }  
  32.     }  
  33.   
  34.     public void put(String id, Bitmap bitmap) {  
  35.         try {  
  36.             if (cache.containsKey(id))  
  37.                 size -= getSizeInBytes(cache.get(id));  
  38.             cache.put(id, bitmap);  
  39.             size += getSizeInBytes(bitmap);  
  40.             checkSize();  
  41.         } catch (Throwable th) {  
  42.             th.printStackTrace();  
  43.         }  
  44.     }  
  45.   
  46.     /** 
  47.      * 严格控制堆内存,如果超过将首先替换最近最少使用的那个图片缓存 
  48.      *  
  49.      */  
  50.     private void checkSize() {  
  51.         Log.i(TAG, "cache size=" + size + " length=" + cache.size());  
  52.         if (size > limit) {  
  53.             // 先遍历最近最少使用的元素  
  54.             Iterator<Entry<String, Bitmap>> iter = cache.entrySet().iterator();  
  55.             while (iter.hasNext()) {  
  56.                 Entry<String, Bitmap> entry = iter.next();  
  57.                 size -= getSizeInBytes(entry.getValue());  
  58.                 iter.remove();  
  59.                 if (size <= limit)  
  60.                     break;  
  61.             }  
  62.             Log.i(TAG, "Clean cache. New size " + cache.size());  
  63.         }  
  64.     }  
  65.   
  66.     public void clear() {  
  67.         cache.clear();  
  68.     }  
  69.   
  70.     /** 
  71.      * 图片占用的内存 
  72.      *  
  73.      * @param bitmap 
  74.      * @return 
  75.      */  
  76.     long getSizeInBytes(Bitmap bitmap) {  
  77.         if (bitmap == null)  
  78.             return 0;  
  79.         return bitmap.getRowBytes() * bitmap.getHeight();  
  80.     }  
  81. }  

也可以使用SoftReference,代码会简单很多,但是我推荐上面的方法。

[java] view
plain
copy

  1. public class MemoryCache {  
  2.       
  3.     private Map<String, SoftReference<Bitmap>> cache = Collections  
  4.             .synchronizedMap(new HashMap<String, SoftReference<Bitmap>>());  
  5.   
  6.     public Bitmap get(String id) {  
  7.         if (!cache.containsKey(id))  
  8.             return null;  
  9.         SoftReference<Bitmap> ref = cache.get(id);  
  10.         return ref.get();  
  11.     }  
  12.   
  13.     public void put(String id, Bitmap bitmap) {  
  14.         cache.put(id, new SoftReference<Bitmap>(bitmap));  
  15.     }  
  16.   
  17.     public void clear() {  
  18.         cache.clear();  
  19.     }  
  20.   
  21. }  

下面是文件缓存类的代码FileCache.java:

[java] view
plain
copy

  1. public class FileCache {  
  2.   
  3.     private File cacheDir;  
  4.   
  5.     public FileCache(Context context) {  
  6.         // 如果有SD卡则在SD卡中建一个LazyList的目录存放缓存的图片  
  7.         // 没有SD卡就放在系统的缓存目录中  
  8.         if (android.os.Environment.getExternalStorageState().equals(  
  9.                 android.os.Environment.MEDIA_MOUNTED))  
  10.             cacheDir = new File(  
  11.                     android.os.Environment.getExternalStorageDirectory(),  
  12.                     "LazyList");  
  13.         else  
  14.             cacheDir = context.getCacheDir();  
  15.         if (!cacheDir.exists())  
  16.             cacheDir.mkdirs();  
  17.     }  
  18.   
  19.     public File getFile(String url) {  
  20.         // 将url的hashCode作为缓存的文件名  
  21.         String filename = String.valueOf(url.hashCode());  
  22.         // Another possible solution  
  23.         // String filename = URLEncoder.encode(url);  
  24.         File f = new File(cacheDir, filename);  
  25.         return f;  
  26.   
  27.     }  
  28.   
  29.     public void clear() {  
  30.         File[] files = cacheDir.listFiles();  
  31.         if (files == null)  
  32.             return;  
  33.         for (File f : files)  
  34.             f.delete();  
  35.     }  
  36.   
  37. }  

最后最重要的加载图片的类,ImageLoader.java:

[java] view
plain
copy

  1. public class ImageLoader {  
  2.   
  3.     MemoryCache memoryCache = new MemoryCache();  
  4.     FileCache fileCache;  
  5.     private Map<ImageView, String> imageViews = Collections  
  6.             .synchronizedMap(new WeakHashMap<ImageView, String>());  
  7.     // 线程池  
  8.     ExecutorService executorService;  
  9.   
  10.     public ImageLoader(Context context) {  
  11.         fileCache = new FileCache(context);  
  12.         executorService = Executors.newFixedThreadPool(5);  
  13.     }  
  14.   
  15.     // 当进入listview时默认的图片,可换成你自己的默认图片  
  16.     final int stub_id = R.drawable.stub;  
  17.   
  18.     // 最主要的方法  
  19.     public void DisplayImage(String url, ImageView imageView) {  
  20.         imageViews.put(imageView, url);  
  21.         // 先从内存缓存中查找  
  22.   
  23.         Bitmap bitmap = memoryCache.get(url);  
  24.         if (bitmap != null)  
  25.             imageView.setImageBitmap(bitmap);  
  26.         else {  
  27.             // 若没有的话则开启新线程加载图片  
  28.             queuePhoto(url, imageView);  
  29.             imageView.setImageResource(stub_id);  
  30.         }  
  31.     }  
  32.   
  33.     private void queuePhoto(String url, ImageView imageView) {  
  34.         PhotoToLoad p = new PhotoToLoad(url, imageView);  
  35.         executorService.submit(new PhotosLoader(p));  
  36.     }  
  37.   
  38.     private Bitmap getBitmap(String url) {  
  39.         File f = fileCache.getFile(url);  
  40.   
  41.         // 先从文件缓存中查找是否有  
  42.         Bitmap b = decodeFile(f);  
  43.         if (b != null)  
  44.             return b;  
  45.   
  46.         // 最后从指定的url中下载图片  
  47.         try {  
  48.             Bitmap bitmap = null;  
  49.             URL imageUrl = new URL(url);  
  50.             HttpURLConnection conn = (HttpURLConnection) imageUrl  
  51.                     .openConnection();  
  52.             conn.setConnectTimeout(30000);  
  53.             conn.setReadTimeout(30000);  
  54.             conn.setInstanceFollowRedirects(true);  
  55.             InputStream is = conn.getInputStream();  
  56.             OutputStream os = new FileOutputStream(f);  
  57.             CopyStream(is, os);  
  58.             os.close();  
  59.             bitmap = decodeFile(f);  
  60.             return bitmap;  
  61.         } catch (Exception ex) {  
  62.             ex.printStackTrace();  
  63.             return null;  
  64.         }  
  65.     }  
  66.   
  67.     // decode这个图片并且按比例缩放以减少内存消耗,虚拟机对每张图片的缓存大小也是有限制的  
  68.     private Bitmap decodeFile(File f) {  
  69.         try {  
  70.             // decode image size  
  71.             BitmapFactory.Options o = new BitmapFactory.Options();  
  72.             o.inJustDecodeBounds = true;  
  73.             BitmapFactory.decodeStream(new FileInputStream(f), null, o);  
  74.   
  75.             // Find the correct scale value. It should be the power of 2.  
  76.             final int REQUIRED_SIZE = 70;  
  77.             int width_tmp = o.outWidth, height_tmp = o.outHeight;  
  78.             int scale = 1;  
  79.             while (true) {  
  80.                 if (width_tmp / 2 < REQUIRED_SIZE  
  81.                         || height_tmp / 2 < REQUIRED_SIZE)  
  82.                     break;  
  83.                 width_tmp /= 2;  
  84.                 height_tmp /= 2;  
  85.                 scale *= 2;  
  86.             }  
  87.   
  88.             // decode with inSampleSize  
  89.             BitmapFactory.Options o2 = new BitmapFactory.Options();  
  90.             o2.inSampleSize = scale;  
  91.             return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);  
  92.         } catch (FileNotFoundException e) {  
  93.         }  
  94.         return null;  
  95.     }  
  96.   
  97.     // Task for the queue  
  98.     private class PhotoToLoad {  
  99.         public String url;  
  100.         public ImageView imageView;  
  101.   
  102.         public PhotoToLoad(String u, ImageView i) {  
  103.             url = u;  
  104.             imageView = i;  
  105.         }  
  106.     }  
  107.   
  108.     class PhotosLoader implements Runnable {  
  109.         PhotoToLoad photoToLoad;  
  110.   
  111.         PhotosLoader(PhotoToLoad photoToLoad) {  
  112.             this.photoToLoad = photoToLoad;  
  113.         }  
  114.   
  115.         @Override  
  116.         public void run() {  
  117.             if (imageViewReused(photoToLoad))  
  118.                 return;  
  119.             Bitmap bmp = getBitmap(photoToLoad.url);  
  120.             memoryCache.put(photoToLoad.url, bmp);  
  121.             if (imageViewReused(photoToLoad))  
  122.                 return;  
  123.             BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);  
  124.             // 更新的操作放在UI线程中  
  125.             Activity a = (Activity) photoToLoad.imageView.getContext();  
  126.             a.runOnUiThread(bd);  
  127.         }  
  128.     }  
  129.   
  130.     /** 
  131.      * 防止图片错位 
  132.      *  
  133.      * @param photoToLoad 
  134.      * @return 
  135.      */  
  136.     boolean imageViewReused(PhotoToLoad photoToLoad) {  
  137.         String tag = imageViews.get(photoToLoad.imageView);  
  138.         if (tag == null || !tag.equals(photoToLoad.url))  
  139.             return true;  
  140.         return false;  
  141.     }  
  142.   
  143.     // 用于在UI线程中更新界面  
  144.     class BitmapDisplayer implements Runnable {  
  145.         Bitmap bitmap;  
  146.         PhotoToLoad photoToLoad;  
  147.   
  148.         public BitmapDisplayer(Bitmap b, PhotoToLoad p) {  
  149.             bitmap = b;  
  150.             photoToLoad = p;  
  151.         }  
  152.   
  153.         public void run() {  
  154.             if (imageViewReused(photoToLoad))  
  155.                 return;  
  156.             if (bitmap != null)  
  157.                 photoToLoad.imageView.setImageBitmap(bitmap);  
  158.             else  
  159.                 photoToLoad.imageView.setImageResource(stub_id);  
  160.         }  
  161.     }  
  162.   
  163.     public void clearCache() {  
  164.         memoryCache.clear();  
  165.         fileCache.clear();  
  166.     }  
  167.   
  168.     public static void CopyStream(InputStream is, OutputStream os) {  
  169.         final int buffer_size = 1024;  
  170.         try {  
  171.             byte[] bytes = new byte[buffer_size];  
  172.             for (;;) {  
  173.                 int count = is.read(bytes, 0, buffer_size);  
  174.                 if (count == -1)  
  175.                     break;  
  176.                 os.write(bytes, 0, count);  
  177.             }  
  178.         } catch (Exception ex) {  
  179.         }  
  180.     }  
  181. }  


上面代码的思路是这样的,首先是一个MemoryCache类,用来缓存图片应用到内存。这个类包含一个Collectiosn.synchronizedMap(new LinkedHashMap<String,Bitmap>(10,1.5f,true))对象,这个对象就是用来保存url和对应的bitmap的,也就是缓存,最后一个参数设置为true的原因,是代表这个map里的元素将按照最近使用次数由少到多排列,即LRU。这样的好处是如果要将缓存中的元素替换,则先遍历出最近最少使用的元素来替换以提高效率 。

另外设置一个缓存的最大值limit,和一个初始值size=0。每次添加图片缓存,Size就增加相应大小,如果增加以后大小超过limit,就遍历LinkedHashMap清楚使用次数最少的缓存,同时减小size值,直到size<limit。

作者还举了一个使用SoftReference的例子,这样做的好处是android会自动替我们回收适当的bitmap缓存。

接下来是文件缓存,如果有SD卡则在SD卡中建一个LazyList的目录存放缓存的图片,没有SD卡就放在系统的缓存目录中,将url的hashCode作为缓存的文件名。这个类只是根据url名创建并返回了一个File类,没有真正的缓存图片,图片缓存在ImageLoader类中,不过这个类要获取FileCache返回的File来做FileOutputStream的目的地.

最后是负责的ImageLoader,这个类有一个线程池,用于管理下载线程。另外有一个WeakHashMap<ImageView, String>用于保存imageview引用和记录Tag,用于图片更新。它先检查缓存,没有则开启一个线程去下载,下载以后图片保存到缓存(内存,文件),然后缩放图像比例,返回一个合适大小的bitmap,最后开启一个线程去跟新UI(方式是imagview.getContext()获取对应的context,然后context调用runOnUIThread()方法)。

另外,在下载线程开启前,图片下载完成后,跟新UI前,都通过WeakHashMap<ImageView, String>获取下载图片的Tag与对应要设置图片imageview的tag比较,防止图片错位。

上述代码完成了基本的优化思路,甚至使用了一个自己定义的缓存类MemoryCache,使管理变得更加清晰,同时有文件缓存,也通过imagview->url的方式避免了图片错位,还开启了异步线程下载图片,但是又开启了一个UI线程去跟新UI。

缺点是开启了UI线程去更新UI,浪费了资源,其实这个可以使用定义一个回调接口实现。另外也没有考虑到重复开启下载线程的问题。

第二个例子:

先贴上主方法的代码:

[java] view
plain
copy

  1. package cn.wangmeng.test;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.lang.ref.SoftReference;  
  6. import java.net.MalformedURLException;  
  7. import java.net.URL;  
  8. import java.util.HashMap;  
  9.   
  10. import android.graphics.drawable.Drawable;  
  11. import android.os.Handler;  
  12. import android.os.Message;  
  13.   
  14. public class AsyncImageLoader {  
  15.   
  16.      private HashMap<String, SoftReference<Drawable>> imageCache;  
  17.         
  18.          public AsyncImageLoader() {  
  19.              imageCache = new HashMap<String, SoftReference<Drawable>>();  
  20.          }  
  21.         
  22.          public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) {  
  23.              if (imageCache.containsKey(imageUrl)) {  
  24.                  SoftReference<Drawable> softReference = imageCache.get(imageUrl);  
  25.                  Drawable drawable = softReference.get();  
  26.                  if (drawable != null) {  
  27.                      return drawable;  
  28.                  }  
  29.              }  
  30.              final Handler handler = new Handler() {  
  31.                  public void handleMessage(Message message) {  
  32.                      imageCallback.imageLoaded((Drawable) message.obj, imageUrl);  
  33.                  }  
  34.              };  
  35.              new Thread() {  
  36.                  @Override  
  37.                  public void run() {  
  38.                      Drawable drawable = loadImageFromUrl(imageUrl);  
  39.                      imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));  
  40.                      Message message = handler.obtainMessage(0, drawable);  
  41.                      handler.sendMessage(message);  
  42.                  }  
  43.              }.start();  
  44.              return null;  
  45.          }  
  46.         
  47.         public static Drawable loadImageFromUrl(String url) {  
  48.             URL m;  
  49.             InputStream i = null;  
  50.             try {  
  51.                 m = new URL(url);  
  52.                 i = (InputStream) m.getContent();  
  53.             } catch (MalformedURLException e1) {  
  54.                 e1.printStackTrace();  
  55.             } catch (IOException e) {  
  56.                 e.printStackTrace();  
  57.             }  
  58.             Drawable d = Drawable.createFromStream(i, "src");  
  59.             return d;  
  60.         }  
  61.         
  62.          public interface ImageCallback {  
  63.              public void imageLoaded(Drawable imageDrawable, String imageUrl);  
  64.          }  
  65.   
  66. }  

以上代码是实现异步获取图片的主方法,SoftReference是软引用,是为了更好的为了系统回收变量,重复的URL直接返回已有的资源,实现回调函数,让数据成功后,更新到UI线程。
几个辅助类文件:

[java] view
plain
copy

  1. package cn.wangmeng.test;  
  2.   
  3. public class ImageAndText {  
  4.         private String imageUrl;  
  5.         private String text;  
  6.   
  7.         public ImageAndText(String imageUrl, String text) {  
  8.             this.imageUrl = imageUrl;  
  9.             this.text = text;  
  10.         }  
  11.         public String getImageUrl() {  
  12.             return imageUrl;  
  13.         }  
  14.         public String getText() {  
  15.             return text;  
  16.         }  
  17. }  

[java] view
plain
copy

  1. package cn.wangmeng.test;  
  2.   
  3. import android.view.View;  
  4. import android.widget.ImageView;  
  5. import android.widget.TextView;  
  6.   
  7. public class ViewCache {  
  8.   
  9.         private View baseView;  
  10.         private TextView textView;  
  11.         private ImageView imageView;  
  12.   
  13.         public ViewCache(View baseView) {  
  14.             this.baseView = baseView;  
  15.         }  
  16.   
  17.         public TextView getTextView() {  
  18.             if (textView == null) {  
  19.                 textView = (TextView) baseView.findViewById(R.id.text);  
  20.             }  
  21.             return textView;  
  22.         }  
  23.   
  24.         public ImageView getImageView() {  
  25.             if (imageView == null) {  
  26.                 imageView = (ImageView) baseView.findViewById(R.id.image);  
  27.             }  
  28.             return imageView;  
  29.         }  
  30.   
  31. }  

ViewCache是辅助获取adapter的子元素布局

[java] view
plain
copy

  1. package cn.wangmeng.test;  
  2.   
  3. import java.util.List;  
  4.   
  5. import cn.wangmeng.test.AsyncImageLoader.ImageCallback;  
  6.   
  7. import android.app.Activity;  
  8. import android.graphics.drawable.Drawable;  
  9. import android.view.LayoutInflater;  
  10. import android.view.View;  
  11. import android.view.ViewGroup;  
  12. import android.widget.ArrayAdapter;  
  13. import android.widget.ImageView;  
  14. import android.widget.ListView;  
  15. import android.widget.TextView;  
  16.   
  17. public class ImageAndTextListAdapter extends ArrayAdapter<ImageAndText> {  
  18.   
  19.         private ListView listView;  
  20.         private AsyncImageLoader asyncImageLoader;  
  21.   
  22.         public ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {  
  23.             super(activity, 0, imageAndTexts);  
  24.             this.listView = listView;  
  25.             asyncImageLoader = new AsyncImageLoader();  
  26.         }  
  27.   
  28.         public View getView(int position, View convertView, ViewGroup parent) {  
  29.             Activity activity = (Activity) getContext();  
  30.   
  31.             // Inflate the views from XML  
  32.             View rowView = convertView;  
  33.             ViewCache viewCache;  
  34.             if (rowView == null) {  
  35.                 LayoutInflater inflater = activity.getLayoutInflater();  
  36.                 rowView = inflater.inflate(R.layout.image_and_text_row, null);  
  37.                 viewCache = new ViewCache(rowView);  
  38.                 rowView.setTag(viewCache);  
  39.             } else {  
  40.                 viewCache = (ViewCache) rowView.getTag();  
  41.             }  
  42.             ImageAndText imageAndText = getItem(position);  
  43.   
  44.             // Load the image and set it on the ImageView  
  45.             String imageUrl = imageAndText.getImageUrl();  
  46.             ImageView imageView = viewCache.getImageView();  
  47.             imageView.setTag(imageUrl);  
  48.             Drawable cachedImage = asyncImageLoader.loadDrawable(imageUrl, new ImageCallback() {  
  49.                 public void imageLoaded(Drawable imageDrawable, String imageUrl) {  
  50.                     ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);  
  51.                     if (imageViewByTag != null) {  
  52.                         imageViewByTag.setImageDrawable(imageDrawable);  
  53.                     }  
  54.                 }  
  55.             });  
  56.             if (cachedImage == null) {  
  57.                 imageView.setImageResource(R.drawable.default_image);  
  58.             }else{  
  59.                 imageView.setImageDrawable(cachedImage);  
  60.             }  
  61.             // Set the text on the TextView  
  62.             TextView textView = viewCache.getTextView();  
  63.             textView.setText(imageAndText.getText());  
  64.   
  65.             return rowView;  
  66.         }  
  67.   
  68. }  

上述代码的思路是这样的:AsyncImageLoader类里面,使用了一个HashMap<String, SoftReference<Drawable>>用来缓存,然后有一个异步下载线程,还有一个方法内部的handler,线程下载完成后,会发消息给handler,然后handler调用回调接口imageCallback的imageLoaded()方法,这个方法是在adapter里面实现的,所以也就是在主线程跟新UI了。

而ViewCache类的作用其实就是ViewHolder,ImageAndText是一个bean类。

在adapter中,使用mageView.setTag(imageUrl)为imageview提供一个唯一标识Url,所以先图片下载完成以后,imageCallback的imageLoaded()方法中,就可以调用listview的findViewWithTag(imageUrl)来找到对应的imageview,从而不用担心错误的问题,这个方法比较巧妙。

缺点是没有实现文件缓存,另外也没有解决出现多个线程下载同一张图片的问题。

时间: 2024-11-10 00:21:02

listview优化(中)的相关文章

Android零基础入门第43节:ListView优化和列表首尾使用

原文:Android零基础入门第43节:ListView优化和列表首尾使用    前面连续几期都在学习ListView的各种使用方法,如果细心的同学可能会发现其运行效率是有待提高的,那么本期就来一起学习有哪些方法技巧来优化ListView的效率.     一.使用convertView       前面讲的自定义ArrayAdapter和自定义BaseAdapter,都会重写getView()方法,虽然可以正常使用,但其实效率非常低.当列表项很多时,用户每次滚动屏幕,都会创建一批新的View对象

我的Android进阶之旅------&amp;gt;Android ListView优化详解

1.ListView的Adapter的作用如下图所示: ListView是Android开发过程中较为常见的组件之一,它将数据以列表的形式展现出来.一般而言,一个ListView由以下三个元素组成:        1.View,用于展示列表,通常是一个xml所指定的.大家都知道Android的界面基本上是由xml文件负责完成的,所以ListView的界面也理所应当的使用了xml定义.例如在ListView中经常用到的"android.R.layout.simple_list_item"

Android ListView优化之提高android应用效率_Android

ListView是一个经常用到的控件,ListView里面的每个子项Item可以使一个字符串,也可以是一个组合控件.Adapter是listview和数据源间的中间人. 当每条数据进入可见区域时,adapter的getview()会被调用,返回代表具体数据的视图.触摸滚动时,频繁调用.支持成百上千条数据. 下面为显示每条数据的xml文件: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

HTML标签图片alt在优化中的谨慎使用

图片中故意充斥大量ALT关键词文本不仅无助于网页的搜索引擎排名,反而会因为有ALT关键词垃圾(ALT Text Spam)嫌疑而影响排名成效 在网页设计中,图片的属性ALT标签用于对图片进行命名等描述说明.ALT标签众多关键词信息在搜索引擎优化中曾发挥了一定作用,常被用于增加网页关键词密度,因此在ALT中合理添加与主题有关的关键词属于搜索引擎优化中考虑的一个因素.不过,最近美国SEO研究网站WebMarketingNow和Search Engine Academy根据长期测试研究认为,目前,三大

TAG标签在SEO优化中的作用

1.TAG标签是什么 很多人还不了解沈阳SEO优化中TAG标签具体是什么东西,对网站沈阳SEO优化又会带来什么样的影响,首先我网站用的CMS里面已经有了添加TAG标签的功能,但是沈阳SEO优化一直以来应用的并不是十分充分,有的时候是空着,有的时候就直接写关键词,这对于一个健康的网站沈阳SEO优化来说也许是不会带来什么fu/mian的影响的,那么这个TAG标签究竟有什么作用呢? TAG标签与关键词有着同样的重要的地位,我认为关键词是写给搜索引擎看的,而TAG标签针对的却是用户,是直接的浏览者.很多

网站优化中如何写出满足用户需求的文章

笔者一直从事的资讯类小企业网站的运维和优化过程,尤其随着百度算法的升级,越发感觉到优质的站内文章对于seo的重要性,作为一个seoer笔者认为文章的撰写一定是和用户需求和体验挂钩的,你的内容能获得多少客户的关注,就能提升网站多大的粘度,这两者是成正比的,一个资讯类网站,如何让文章质量更有价值和说服力,笔者认为以下几个方面值得我们任何一个站长的思考,好了下面笔者以自己网站为案例进行详细分析. 第一,撰写之前如何有效挖掘用户需求.笔者非常喜欢进行数据统计工作,我们先来看图, 以上图示内容展示的是百度

浅谈在网站优化中如何提升外链质量

在网站优化过程中,影响因素除了内链和原创内容外,外链也是影响站外SEO成功与否的关键.外链优化不是指要无限的增加外链数量,而是要比较注重它的品质.只有这类外链才会对网站优化权重会起一定的辅助性作用,下面就由星梦网络来谈下在网站优化中如何提升外链质量. 网站外链需要多样性 在进行站外优化中,增长外链不要知道它的数量外而忽略了它的多样性.在网站优化中,我们要不断收集各行各业的网站外链资源,也可以在这些不同的外链资源中留下文本链接,而且最好是文本超链接.虽然现在有许多可以带外链的网站,但是在有些网站中

浅谈在网站优化中获取高质量外链有哪些渠道

在网站优化过程过,有一个是比较让一些站长头疼的事,那就是寻找网站外链的渠道.有的网站可以让我们带外链但是JS形式,有的网站可以带超链接的但里面却加了nofollow标签,这些外链资源加了也等于没有加.那么我们在网站优化中,到底获取高质量外链有哪些渠道呢? 新闻源媒体 其实现在在网上有许多可以投稿的高权重新闻媒体,这些网站除了有比较高的人气和流量外,而且你所投的稿子被第三方网站转载的频率是相当高的,前提是你的稿子质量和相关性都比较好,这样带来的效果也是比较不错的. 如果是比较有实力的站长,你也可以

URL优化中6个需要注意的事项

在网站的优化中,URL的优化是大家经常的忽视的一个方面,但是URL的优化也同样是非常重要的,这里就和大家谈谈我是怎么处理这些问题的,希望这些经验对大家有所帮助! 1:域名的选择 不要为了让域名中出现关键词而全拼域名,这样我们的域名就显得非常的长了,也不要为了放关键词,注册带有连词符的域名. 2:文件夹命名 整个URL包括域名,文件名,用网站合适的关键词,尤其是文件名.让浏览者一看到看到URL,就可以大致了解这个网页是什么内容,Z-BLOG在这一点就做的非常的好,我搜索我自己博客的关键词,发现在U

网站优化中三大SEO要素

SEO是一门入门简单,但是无法完全琢磨透的技术,任何一个SEO高手只能做到无限接近搜索引擎的算法,而永远不可能掌握搜索引擎的算法.它主要研究的是搜索引擎页面上的自然排名部分,即页面的左侧部分,一般来说与付费广告(PPC)没有直接关系.SEO优化对于网站来说主要可以分成站内优化以及站外优化两部分,这里主要讲在站内.站外优化中较为重要的网页标题的编写.正文中关键词的分布以及如何做外部链接. 标题 网页标题指的是包含在title标签内的文字,是用户在使用搜索引擎时直接看到的内容,可以说是网页优化最重要