Android_Glide源码分析

Android_Glide源码分析


本文由 Luzhuo 编写,转发请保留该信息.
原文: http://blog.csdn.net/Rozol/article/details/73252999


Glide源码讲解

基本使用

Glide.with(this).load(url).into(imageview);

源码讲解

  1. 看下.with(this)做了什么

    public static RequestManager with(Context context) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(context);
    }
    
    public RequestManager get(Context context) {
        if (context == null) {
            throw new IllegalArgumentException("You cannot start a load on a null Context");
        } else if (Util.isOnMainThread() && !(context instanceof Application)) { // ←←←
            if (context instanceof FragmentActivity) {
                return get((FragmentActivity) context);
            } else if (context instanceof Activity) {
                return get((Activity) context);
            } else if (context instanceof ContextWrapper) {
                return get(((ContextWrapper) context).getBaseContext());
            }
        }
    
        return getApplicationManager(context);
    }
    
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public RequestManager get(Activity activity) {
        if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
            return get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity); // ←←←
            android.app.FragmentManager fm = activity.getFragmentManager(); // ←←←
            return fragmentGet(activity, fm);
        }
    }
    
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
        RequestManagerFragment current = getRequestManagerFragment(fm); // ←←←
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
            requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }
    
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {
        RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
            current = pendingRequestManagerFragments.get(fm);
            if (current == null) {
                current = new RequestManagerFragment();
                pendingRequestManagerFragments.put(fm, current);
                fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
                handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
            }
        }
        return current;
    }
    • 先调用Util.isOnMainThread()判断是否在主线程

      public static boolean isOnMainThread() {
          return Looper.myLooper() == Looper.getMainLooper();
      }
       - 判断是否在主线程,原来是通过判断是否是主线程的Looper来判断的
      
    • 先调用assertNotDestroyed(activity)断言Activity还没有Destroy, 然后调用activity.getFragmentManager()获得一个FragmentManager
    • 调用getRequestManagerFragment(fm)获得RequestManagerFragment, 这个其实是一个用于实现生命周期管理的Fragment, 通过Fragment的回调管理RequestManager

      public class RequestManagerFragment extends Fragment {
          @SuppressLint("ValidFragment")
          RequestManagerFragment(ActivityFragmentLifecycle lifecycle) {
              this.lifecycle = lifecycle;
          }
      
          @Override
          public void onStart() {
              super.onStart();
              lifecycle.onStart();
          }
      
          @Override
          public void onStop() {
              super.onStop();
              lifecycle.onStop();
          }
      
          @Override
          public void onDestroy() {
              super.onDestroy();
              lifecycle.onDestroy();
          }
      }
      • 可见RequestManager实现了LifecycleListener

        public class RequestManager implements LifecycleListener {
            RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
                    RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
                this.context = context.getApplicationContext();
                this.lifecycle = lifecycle;
                this.treeNode = treeNode;
                this.requestTracker = requestTracker;
                this.glide = Glide.get(context);
                this.optionsApplier = new OptionsApplier();
        
                ConnectivityMonitor connectivityMonitor = factory.build(context,
                        new RequestManagerConnectivityListener(requestTracker));
        
                // If we're the application level request manager, we may be created on a background thread. In that case we
                // cannot risk synchronously pausing or resuming requests, so we hack around the issue by delaying adding
                // ourselves as a lifecycle listener by posting to the main thread. This should be entirely safe.
                if (Util.isOnBackgroundThread()) {
                    new Handler(Looper.getMainLooper()).post(new Runnable() {
                        @Override
                        public void run() {
                            lifecycle.addListener(RequestManager.this);
                        }
                    });
                } else {
                    lifecycle.addListener(this);
                }
                lifecycle.addListener(connectivityMonitor);
            }
        
            @Override
            public void onStart() {
                // onStart might not be called because this object may be created after the fragment/activity's onStart method.
                resumeRequests();
            }
        
            @Override
            public void onStop() {
                pauseRequests();
            }
        
            @Override
            public void onDestroy() {
                requestTracker.clearRequests();
            }
        }
  2. 上面我们得到了RequestManager的对象,接着调用.load(url)

    public DrawableTypeRequest load(String string) {
        return (DrawableTypeRequest) fromString().load(string);
    }
    
    @Override
    public DrawableRequestBuilder load(ModelType model) {
        super.load(model);
        return this;
    }
    
    public GenericRequestBuilder load(ModelType model) {
        this.model = model;
        isModelSet = true;
        return this;
    }
    • 这个很简单,就是给GenericRequestBuilder初始化值, 并返回了DrawableRequestBuilder
  3. 接着看.into(imageview)

    @Override
    public Target into(ImageView view) {
        return super.into(view);
    }
    
    public > Y into(Y target) {
       Util.assertMainThread();
       if (target == null) {
           throw new IllegalArgumentException("You must pass in a non null Target");
       }
       if (!isModelSet) {
           throw new IllegalArgumentException("You must first set a model (try #load())");
       }
    
    // ↓↓↓
       Request previous = target.getRequest();
    
       if (previous != null) {
           previous.clear();
           requestTracker.removeRequest(previous);
           previous.recycle();
       }
    
    // ↓↓↓
       Request request = buildRequest(target);
       target.setRequest(request);
       lifecycle.addListener(target);
       requestTracker.runRequest(request);
    
       return target;
    }
  4. 整理后的流程图
    Android_Glide源码分析_第1张图片

其他

通过Fragment的生命周期实现自身的管理

  • XXX管理的代码

    package me.luzhuo.glidedemo.other.lifecycle;
    
    import android.content.Context;
    import android.os.Handler;
    import android.os.Looper;
    import android.util.Log;
    
    import me.luzhuo.glidedemo.other.lifecycle.inter.Lifecycle;
    import me.luzhuo.glidedemo.other.lifecycle.inter.LifecycleListener;
    
    public class Manager implements LifecycleListener {
        private final String TAG = Manager.class.getSimpleName();
        private final Context context;
        private final Lifecycle lifecycle;
    
        public Manager(Context context, final Lifecycle lifecycle) {
            this.context = context.getApplicationContext();
            this.lifecycle = lifecycle;
    
            if (!Utils.isOnMainThread()) {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        lifecycle.addListener(Manager.this);
                    }
                });
            } else {
                lifecycle.addListener(this);
            }
        }
    
        public static Manager with(Context context) {
            ManagerRetriever retriever = ManagerRetriever.get();
            return retriever.get(context);
        }
    
        @Override
        public void onStart() {
            Log.e(TAG, "Manager 将开始工作");
        }
    
        @Override
        public void onStop() {
            Log.e(TAG, "Manager 将暂停工作");
        }
    
        @Override
        public void onDestroy() {
            Log.e(TAG, "Manager 将停止工作");
        }
    }
  • ManagerRetriever主要做的是构建Fragment,并绑定鉴定,这里的代码多,是因为传入Content做相应的Fragment生成和管理

    public class ManagerRetriever {
        Manager applicationManager;
        static final String FRAGMENT_TAG = "me.luzhuo.glidedemo";
        private static final ManagerRetriever INSTANCE = new ManagerRetriever();
    
        public static ManagerRetriever get() {
            return INSTANCE;
        }
    
        public Manager get(Context context) {
            if (context == null) {
                throw new IllegalArgumentException("You cannot start a load on a null Context");
            } else if (Utils.isOnMainThread() && !(context instanceof Application)) {
                if (context instanceof FragmentActivity) {
                    return get((FragmentActivity) context);
                } else if (context instanceof Activity) {
                    return get((Activity) context);
                } else if (context instanceof ContextWrapper) {
                    return get(((ContextWrapper) context).getBaseContext());
                }
            }
            return getApplicationManager(context);
        }
    
        public Manager get(FragmentActivity activity) {
            if (!Utils.isOnMainThread()) {
                return get(activity.getApplicationContext());
            } else {
                assertNotDestroyed(activity);
                FragmentManager fm = activity.getSupportFragmentManager();
                return fragmentGet(activity, fm);
            }
        }
    
        public Manager get(Fragment fragment) {
            if (fragment.getActivity() == null) {
                throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
            }
            if (!Utils.isOnMainThread()) {
                return get(fragment.getActivity().getApplicationContext());
            } else {
                FragmentManager fm = fragment.getChildFragmentManager();
                return fragmentGet(fragment.getActivity(), fm);
            }
        }
    
        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        public Manager get(Activity activity) {
            if (!Utils.isOnMainThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
                return get(activity.getApplicationContext());
            } else {
                assertNotDestroyed(activity);
                android.app.FragmentManager fm = activity.getFragmentManager();
                return fragmentGet2(activity, fm);
            }
        }
    
        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        private static void assertNotDestroyed(Activity activity) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed()) {
                throw new IllegalArgumentException("You cannot start a load for a destroyed activity");
            }
        }
    
        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        public Manager get(android.app.Fragment fragment) {
            if (fragment.getActivity() == null) {
                throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
            }
            if (!Utils.isOnMainThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
                return get(fragment.getActivity().getApplicationContext());
            } else {
                android.app.FragmentManager fm = fragment.getChildFragmentManager();
                return fragmentGet2(fragment.getActivity(), fm);
            }
        }
    
        private Manager getApplicationManager(Context context) {
            // Either an application context or we're on a background thread.
            if (applicationManager == null) {
                synchronized (this) {
                    if (applicationManager == null) {
                        applicationManager = new Manager(context.getApplicationContext(), getLifecycle);
                    }
                }
            }
            return applicationManager;
        }
    
        Lifecycle getLifecycle = new Lifecycle() {
            @Override
            public void addListener(LifecycleListener listener) {
                listener.onStart();
            }
        };
    
        Manager fragmentGet(Context context, FragmentManager fm) {
            LifecycleFragment current = getManagerFragment(fm);
            Manager manager = current.getManager();
            if (manager == null) {
                manager = new Manager(context, current.getLifecycle());
                current.setManager(manager);
            }
            return manager;
        }
    
        @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        Manager fragmentGet2(Context context, android.app.FragmentManager fm) {
            LifecycleFragment2 current = getManagerFragment2(fm);
            Manager manager = current.getManager();
            if (manager == null) {
                manager = new Manager(context, current.getLifecycle());
                current.setManager(manager);
            }
            return manager;
        }
    
        LifecycleFragment getManagerFragment(final FragmentManager fm) {
            LifecycleFragment current = (LifecycleFragment) fm.findFragmentByTag(FRAGMENT_TAG);
            if (current == null) {
                if (current == null) {
                    current = new LifecycleFragment();
                    fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
                }
            }
            return current;
        }
    
        LifecycleFragment2 getManagerFragment2(final android.app.FragmentManager fm) {
            LifecycleFragment2 current = (LifecycleFragment2) fm.findFragmentByTag(FRAGMENT_TAG);
            if (current == null) {
                if (current == null) {
                    current = new LifecycleFragment2();
                    fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
                }
            }
            return current;
        }
    }
  • Utils就一个isOnMainThread()方法,根据Looper判断是否是主线程

    public class Utils {
        public static boolean isOnMainThread() {
            return Looper.myLooper() == Looper.getMainLooper();
        }
    }
  • 有两个Fragment,由于代码一样,仅仅是Fragment的包的引用不同,这里就写一份吧

    package me.luzhuo.glidedemo.other.lifecycle.fragment;
    
    import android.annotation.SuppressLint;
    import android.app.Activity;
    import android.support.v4.app.Fragment;
    import android.util.Log;
    
    import me.luzhuo.glidedemo.other.lifecycle.Manager;
    import me.luzhuo.glidedemo.other.lifecycle.inter.LifecycleImpl;
    
    public class LifecycleFragment extends Fragment{
        private static final String TAG = LifecycleFragment.class.getSimpleName();
        private Manager manager;
        private final LifecycleImpl lifecycle;
    
    
        public LifecycleFragment() {
            this(new LifecycleImpl());
        }
    
        // For testing only.
        @SuppressLint("ValidFragment")
        public LifecycleFragment(LifecycleImpl lifecycle) {
            this.lifecycle = lifecycle;
        }
    
        public LifecycleImpl getLifecycle() {
            return lifecycle;
        }
    
        public void setManager(Manager manager) {
            this.manager = manager;
        }
    
        public Manager getManager() {
            return this.manager;
        }
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            Log.e(TAG, "onAttach");
        }
    
        @Override
        public void onDetach() {
            super.onDetach();
            Log.e(TAG, "onDetach");
        }
    
        @Override
        public void onStart() {
            super.onStart();
            Log.e(TAG, "onStart");
            lifecycle.onStart();
        }
    
        @Override
        public void onStop() {
            super.onStop();
            Log.e(TAG, "onStop");
            lifecycle.onStop();
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.e(TAG, "onDestroy");
            lifecycle.onDestroy();
        }
    
        @Override
        public void onLowMemory() {
            Log.e(TAG, "onLowMemory");
            super.onLowMemory();
        }
    }
  • 接下来是定义的一些接口,和接口的实现

    public interface Lifecycle {
        void addListener(LifecycleListener listener);
    }
    
    
    public class LifecycleImpl implements Lifecycle {
        private final List lifecycleListeners = new ArrayList();
        private boolean isStarted;
        private boolean isDestroyed;
    
        @Override
        public void addListener(LifecycleListener listener) {
            lifecycleListeners.add(listener);
    
            if (isDestroyed) {
                listener.onDestroy();
            } else if (isStarted) {
                listener.onStart();
            } else {
                listener.onStop();
            }
        }
    
        public void onStart() {
            isStarted = true;
            for (LifecycleListener lifecycleListener : lifecycleListeners) {
                lifecycleListener.onStart();
            }
        }
    
        public void onStop() {
            isStarted = false;
            for (LifecycleListener lifecycleListener : lifecycleListeners) {
                lifecycleListener.onStop();
            }
        }
    
        public void onDestroy() {
            isDestroyed = true;
            for (LifecycleListener lifecycleListener : lifecycleListeners) {
                lifecycleListener.onDestroy();
            }
        }
    }
    
    
    public interface LifecycleListener {
    
        void onStart();
    
        void onStop();
    
        void onDestroy();
    }
    • 用于测试的Activity
    public class LifecycleTestActivity extends AppCompatActivity {
        private static final String TAG = "Test";
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Manager.with(this);
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            Log.e(TAG, "onStart");
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            Log.e(TAG, "onStop");
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.e(TAG, "onDestroy");
        }
    }
  • 打印测试结果
    Android_Glide源码分析_第2张图片

LinkedHashMap的数据结构和算法

  • 首先看下该数据结构的构造方法

    public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
        private transient LinkedHashMapEntry header;
        private final boolean accessOrder;
    
        public LinkedHashMap(int initialCapacity,
                             float loadFactor,
                             boolean accessOrder) {
            super(initialCapacity, loadFactor);
            this.accessOrder = accessOrder;
        }
    
        @Override
        void init() {
            header = new LinkedHashMapEntry<>(-1, null, null, null);
            header.before = header.after = header;
        }
    }
    - 我们可以看到有一个`LinkedHashMapEntry header`**头结点**,还有一个布尔类型的`accessOrder`用来控制是否按访问顺序排序
    
  • 看数据结构,当然必须先把结点理清楚

    private static class LinkedHashMapEntry<K,V> extends HashMapEntry<K,V> {
        // These fields comprise the doubly linked list used for iteration.
        LinkedHashMapEntry before, after;
    
        LinkedHashMapEntry(int hash, K key, V value, HashMapEntry next) {
            super(hash, key, value, next);
        }
    
        /**
         * Removes this entry from the linked list.
         */
        private void remove() {
            before.after = after;
            after.before = before;
        }
    
        /**
         * Inserts this entry before the specified existing entry in the list.
         */
        private void addBefore(LinkedHashMapEntry existingEntry) {
            after  = existingEntry;
            before = existingEntry.before;
            before.after = this;
            after.before = this;
        }
    
        /**
         * This method is invoked by the superclass whenever the value
         * of a pre-existing entry is read by Map.get or modified by Map.set.
         * If the enclosing Map is access-ordered, it moves the entry
         * to the end of the list; otherwise, it does nothing.
         */
        void recordAccess(HashMap m) {
            LinkedHashMap lm = (LinkedHashMap)m;
            if (lm.accessOrder) {
                lm.modCount++;
                remove();
                addBefore(lm.header);
            }
        }
    
        void recordRemoval(HashMap m) {
            remove();
        }
    }
    • 从结点内内LinkedHashMapEntry before, after可以看出这是一个双向循环的链式数据结构
    • 可见数据结构是这样的,接下来我们就来仔细分析下结点里的代码
      Android_Glide源码分析_第3张图片
    • remove()移除结点
      Android_Glide源码分析_第4张图片
    • addBefore()在指定结点前添加结点
      Android_Glide源码分析_第5张图片
    • recordAccess()在记录访问次数,lm.modCount++访问次数+1, 然后通过remove()删除结点,再将自己addBefore(lm.header)添加到头结点之前,也就是链表的末尾
    • recordRemoval()删除访问记录,只是简单的删除了结点
  • 链式的数据结构基本讲解的差不多了, 接下来简单的讲下 增删查

    • 增加

      void createEntry(int hash, K key, V value, int bucketIndex) {
          HashMapEntry old = table[bucketIndex];
          LinkedHashMapEntry e = new LinkedHashMapEntry<>(hash, key, value, old);
          table[bucketIndex] = e;
          e.addBefore(header);
          size++;
      }
      • 创建结点,创建后将结点添加到链表的末尾
    • public void clear() {
          super.clear();
          header.before = header.after = header;
      }
      • 将header结点的before和after指针都指向自己
    • 查(获取)

      public V get(Object key) {
          LinkedHashMapEntry e = (LinkedHashMapEntry)getEntry(key);
          if (e == null)
              return null;
          e.recordAccess(this);
          return e.value;
      }
      • 根据key从hashmap中获取Entry,然后对该结点进行访问记录,返回其值

LruCache

  • 基本使用;

    • LruCache使用代码:

      import android.annotation.SuppressLint;
      import android.graphics.Bitmap;
      import android.os.Build;
      import android.support.v4.util.LruCache;
      import android.util.Log;
      
      public class ImageCache {
          // 使用最大可用内存值的1/5作为缓存的大小。
          private static final int MAXSIZE = (int) (Runtime.getRuntime().maxMemory() / 5);
      
          private static ImageCache cache = new ImageCache();
      
          public static ImageCache getInstance() {
              return cache;
          }
      
          // LruCache<标记, 图片>
          private LruCache lrucache;// 图片的缓存;设置的Value必须能够计算出所占有的内存的大小
      
          private ImageCache() {
              lrucache = new LruCache(MAXSIZE) {
      
                  @Override
                  protected int sizeOf(Object key, Bitmap value) {
                      System.out.println("内存已缓存:"+lrucache.size()+";总空间:"+MAXSIZE);
                      // size的变动代表该bitmap占用的内存大小
                      return getSize(value);
                  }
      
                  @Override
                  protected void entryRemoved(boolean evicted, Object key, Bitmap oldValue, Bitmap newValue) {
                      // evicted 为true表示MAXSIZE不够用
                      if (evicted) {
                          Log.d("memoryLruCache", "remove:" + key.toString());
                      }
                      super.entryRemoved(evicted, key, oldValue, newValue);
                  }
              };
          }
      
          /**
           * 获取图片占用内存的大小
           * @param value
           * @return
           */
          @SuppressLint("NewApi")
          private int getSize(Bitmap value) {
              // 如果当前版本 >= API12
              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
                  return value.getByteCount();
              }
              return value.getRowBytes() * value.getHeight();
          }
      
          /**
           * 添加图片,如果添加的图片超过了设置的最大内存缓存,将清除一部分旧的图片
           * @param key
           * @param value
           */
          public void put(Object key, Bitmap value) {
              lrucache.put(key, value);
          }
      
          public Bitmap get(Object key) {
              Bitmap bitmap = lrucache.get(key);
              return bitmap;
          }
      
          /**
           * 清空所有缓存,包括内存和磁盘
           */
          public void clear() {
              lrucache.evictAll();
          }
      }
    • 测试代码:

      package me.luzhuo.lrucachedemo;
      
      import android.graphics.Bitmap;
      import android.graphics.BitmapFactory;
      import android.os.Environment;
      import android.support.v7.app.AppCompatActivity;
      import android.os.Bundle;
      import android.view.View;
      import android.view.ViewGroup;
      import android.widget.BaseAdapter;
      import android.widget.ImageView;
      import android.widget.ListView;
      import android.widget.TextView;
      
      import java.io.File;
      
      import me.luzhuo.lrucachedemo.utils.ImageCache;
      
      import static android.R.attr.bitmap;
      import static android.R.attr.key;
      
      public class MainActivity extends AppCompatActivity {
          private ListView listview;
          private int key;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              // 添加到内存缓存
              Bitmap bitmap = BitmapFactory.decodeFile(new File(Environment.getExternalStorageDirectory(),"abc.jpg").getPath());
      
              // hashcode的计算方法
              key = bitmap.hashCode();
              key = 31 * key + MainActivity.class.getSimpleName().hashCode();
      
              ImageCache.getInstance().put(key, bitmap);
      
              initView();
              initData();
          }
      
          private void initView() {
              listview = (ListView) findViewById(R.id.listView);
          }
      
          private void initData() {
              listview.setAdapter(new ImageAdapter());
          }
      
          class ImageAdapter extends BaseAdapter {
      
              @Override
              public int getCount() {
                  return 100;
              }
      
              @Override
              public Object getItem(int position) {
                  return null;
              }
      
              @Override
              public long getItemId(int position) {
                  return 0;
              }
      
              class ViewHodler{
                  TextView textview;
                  ImageView imageview;
              }
      
              @Override
              public View getView(int position, View convertView, ViewGroup parent) {
                  ViewHodler viewHodler;
                  if(convertView==null){
                      viewHodler = new ViewHodler();
                      convertView = View.inflate(MainActivity.this, R.layout.item, null);
                      viewHodler.textview = (TextView) convertView.findViewById(R.id.textview);
                      viewHodler.imageview = (ImageView) convertView.findViewById(R.id.imageview);
                      convertView.setTag(viewHodler);
                  }else{
                      viewHodler = (ViewHodler) convertView.getTag();
                  }
      
                  viewHodler.textview.setText("第"+position+"张");
                  // 从内存缓存获取数据
                  Bitmap bitmap = ImageCache.getInstance().get(key);
                  viewHodler.imageview.setImageBitmap(bitmap);
      
                  return convertView;
              }
      
          }
      }
  • 源码解析:

    1. 首先看下构造方法

      public class LruCache<K, V> {
          private final LinkedHashMap map;
      
          /** Size of this cache in units. Not necessarily the number of elements. */
          private int size;
          private int maxSize;
      
          private int putCount;
          private int createCount;
          private int evictionCount;
          private int hitCount;
          private int missCount;
      
          /**
           * @param maxSize for caches that do not override {@link #sizeOf}, this is
           *     the maximum number of entries in the cache. For all other caches,
           *     this is the maximum sum of the sizes of the entries in this cache.
           */
          public LruCache(int maxSize) {
              if (maxSize <= 0) {
                  throw new IllegalArgumentException("maxSize <= 0");
              }
              this.maxSize = maxSize;
              this.map = new LinkedHashMap(0, 0.75f, true);
          }
      }
      • 我们可以得知,maxSize用于限制资源最大的可使用内存, 用LinkedHashMap map来存储资源,并且要求LinkedHashMap访问记录
    2. 接着看下添加资源的方法

      public final V put(K key, V value) {
          if (key == null || value == null) {
              throw new NullPointerException("key == null || value == null");
          }
      
          V previous;
          synchronized (this) {
              putCount++;
              size += safeSizeOf(key, value);
              previous = map.put(key, value);
              if (previous != null) {
                  size -= safeSizeOf(key, previous);
              }
          }
      
          if (previous != null) {
              entryRemoved(false, key, previous, value);
          }
      
          trimToSize(maxSize);
          return previous;
      }
      • 可见添加资源时,会回调safeSizeOf(key, value)获取该资源的大小,然后加到size, 然后调用LinkedHashMap的put()方法添加资源,返回previous

        • 在LinkedHashMap中没有put()方法,看来是调用了HashMap的put()方法

          public V put(K key, V value) {
          
              // ...
          
              for (HashMapEntry e = table[i]; e != null; e = e.next) {
                  Object k;
                  if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                      V oldValue = e.value;
                      e.value = value;
                      e.recordAccess(this);
                      return oldValue;
                  }
              }
          
              modCount++;
              addEntry(hash, key, value, i);
              return null;
          }
        • 调用HashMap的put(),如果这个key已经存在则返回旧元素,否则会调用addEntry()添加元素,然后返回null

          void addEntry(int hash, K key, V value, int bucketIndex) {
          
              // ...
          
              createEntry(hash, key, value, bucketIndex);
          }
        • 然后会调用LinkedHashMap中的createEntry()方法,因为LinkedHashMap重写了该方法,该方法创建了一个结点,并将其添加到链表末尾

      • 我们继续往下看,如果previous返回不为null,说明这个元素存在,调用了size -= safeSizeOf(key, previous),把加上的资源大小减掉

      • 然后会回调entryRemoved(false, key, previous, value)告知该资源没有添加到LruCache里,第一个boolean值表示该资源是否是因为超过限制而被移除,false表示不是,true表示是内存不足而删除.
      • 然后调用trimToSize(maxSize),我们看下做了什么

        public void trimToSize(int maxSize) {
            while (true) {
                K key;
                V value;
                synchronized (this) {
                    if (size < 0 || (map.isEmpty() && size != 0)) {
                        throw new IllegalStateException(getClass().getName()
                                + ".sizeOf() is reporting inconsistent results!");
                    }
        
                    if (size <= maxSize || map.isEmpty()) {
                        break;
                    }
        
                    Map.Entry toEvict = map.entrySet().iterator().next();
                    key = toEvict.getKey();
                    value = toEvict.getValue();
                    map.remove(key);
                    size -= safeSizeOf(key, value);
                    evictionCount++;
                }
        
                entryRemoved(true, key, value, null);
            }
        }
        • 可知原来是在判断添加数据后size是否超过了maxSize,如果超过了就删除元素,直到size <= maxSize || map.isEmpty()为止,删除数据是从LinkedHashMap第一个数据开始删的,因为被访问的元素都在链表末尾,第一个元素恰恰是最少被访问的
    3. 然后在看下获取资源的方法

      public final V get(K key) {
          if (key == null) {
              throw new NullPointerException("key == null");
          }
      
          V mapValue;
          synchronized (this) {
              mapValue = map.get(key);
              if (mapValue != null) {
                  hitCount++;
                  return mapValue;
              }
              missCount++;
          }
      
          // ...
      }
      • 就是调用LinkedHashMap的get()方法,该被访问的结点会被移到列表末尾
    4. 清空缓存

      public final void evictAll() {
          trimToSize(-1); // -1 will evict 0-sized elements
      }
      • 也很简单,就是调用trimToSize(maxSize)把数据全部删掉,trimToSize(maxSize)的源码上面2拷贝过了,不再重复拷贝一份

你可能感兴趣的:(android)