zoukankan      html  css  js  c++  java
  • 8.4.2 Fresco

    Fresco是Facebook公司的黑科技:http://fresco-cn.org/

       真三级缓存,变换后的BItmap(内存),变换前的原始图片(内存),硬盘缓存。在内存管理上做到了极致。对于重度图片使用的APP应该是非常好的。它一般是直接使用SimpleDraweeView来替换ImageView

       注意事项:SimpleDraweeView的width和height属性必须是明确值,而不能直接用wrap_content这种内容填充的数值;除非宽度和高度有一个是固定的,然后设置了二者的比例(setAspectRatio),则另一个可以用wrap_content,其实相当于二者都是固定的。正常情况下,一个SimpleDraweeView的各种属性,既可以在布局文件里面设置(如上面的代码)也可以在Java代码里设置,作用是一样的。但当SimpleDraweeView被被一些第三方自定义View包裹的时候,比如一个可下拉刷新的第三方ListView,则此时在布局文件中的一些属性居然是无效的!

       ImageLoader 等传统第三方图片处理SDK 不同,Fresco 是基于控件级别的,所以我们把程序中显示网络图片的ImageView 都替换为SimpleDraweeView 。

    Fresco 的原理是,设计了一个Image Pipeline 的概念,它负责先后检查内存、磁盘文件(Disk),如果都没有再从网络下载图片。我们可以像配置ImageLoader 那样配置Fresco 中的Image Pipeline,使用ImagePipelineConfig来做这个事情。
      Fresco 有3 个线程池,其中3 个线程用于网络下载图片,2 个线程用于磁盘文件的读写,还有2 个线程用于CPU 相关操作,比如图片解码、转换,以及放在后台执行的一些费时操作。
      接下来介绍Fresco 三层缓存的概念。这才是Fresco 最核心的技术,它比其他图片SDK吃内存小,就在于这个全新的缓存设计。

    • 第一层:Bitmap 缓存:在Android 5.0 系统中,考虑到内存管理有了很大改进,所以Bitmap 缓存位于Java 的堆(heap)中。 ‰而在Android 4.x 和更低的系统,Bitmap 缓存位于ashmem(匿名共享内存) 中,而不是位于Java 的堆(heap)中。这意味着图片的创建和回收不会引发过多的GC,从而让App 运行得更快。当App 切换到后台时,Bitmap 缓存会被清空。
    • 第二层:内存缓存:内存缓存中存储了图片的原始压缩格式。从内存缓存中取出的图片,在显示前必须先解码。当App 切换到后台时,内存缓存也会被清空。
    • 第三层:磁盘缓存:磁盘缓存,又名本地存储。磁盘缓存中存储的也是图片的原始压缩格式。在使用前也要先解码。当App 切换到后台时,磁盘缓存不会丢失,即使关机也不会。

    Fresco 有很多高级的应用,对于大部分App 而言,基本还用不到。

    Image pipeline 负责完成加载图像,变成Android设备可呈现的形式所要经历的大致流程如下: 

    • a、根据Uri在已解码的(Bitmap缓存)内存缓存中查找,找到了则返回Bitmap对象;
    • b、如果没找到,则开启后台线程开始后续的工作。 
    • c、根据Uri在未解码的内存缓存中查找,若找到了则解码,然后缓存到已解码的内存缓存中,并且返回Bitmap对象。 
    • d、如果在未解码的内存缓存中没找到,则根据Uri在磁盘缓存中查找,若找到了则读取数据(byte数组),并缓存到未解码的内存缓存中,解码、然后缓存到已解码的内存缓存中,并且返回Bitmap对象。 
    • e、如果在磁盘缓存中没找到,则从网络或者本地加载数据。加载完成后,依次缓存到磁盘缓存未解码的内存缓存中。解码、然后缓存到已解码的内存缓存中,并且返回Bitmap对象。

    Drawees 

      Fresco 中设计有一个叫做 Drawees 模块,负责图片的呈现。它由三个元素组成分别是: 
          DraweeView 继承于 View, 负责图片的显示。 
          DraweeHierarchy 用于组织和维护最终绘制和呈现的 Drawable 对象。 
          DraweeController 负责和ImagePipeline的交互,可以创建一个这个类的实例,来实现对所要显示的图片做更多的控制。 
      一般情况下,使用 SimpleDraweeView 即可,你可以配置其XML属性来实现各式各样的展示效果。

    a、在图片加载完成前显示占位图; 
    b、在图片加载的过程中显示加载进度图; 
    c、加载成功后,将占位图或者加载进度图,自动替换为目标图片。 
    d、加载失败后,它会显示加载失败的图(若没配置加载失败的图,则显示的是占位图) 
    e、加载失败后,若配置过重试图,则会显示重试图,用户点击可以重新去加载图片(默认配置可重试3次) 
    f、自定义居中焦点(配合Google提供的服务可以实现人脸识别,经测试国内目前使用不了) 
    g、显示圆角图、圆形图和圆圈; 
    h、添加覆盖物(图层叠加); 
    j、 实现图片的按下效果; 
    k、图片的渐进式呈现;(目前只支持Jpeg格式的图片) 
    x、当图片不再显示在屏幕上时,它会及时地释放内存和空间占用。

    Fresco目前所支持的图片格式 
        静态图:png、jpg、web     动态图:gif、web格式的gif


    DEMO:Fresco + RecyclerView三种样式加载本机图片

           

    1、在build.gradle文件中添加依赖

    dependencies {
        // ......
    
        compile 'com.facebook.fresco:fresco:0.14.1'
        compile 'com.facebook.fresco:animated-base-support:0.14.1'  // 在 API < 14 上的机器支持 WebP 时
        compile 'com.facebook.fresco:animated-gif:0.14.1'       // 支持GIF动图
        compile 'com.facebook.fresco:webpsupport:0.14.1'       // 支持WebP
        compile 'com.facebook.fresco:animated-webp:0.14.1'      // 支持WebP动图
        compile 'com.facebook.fresco:imagepipeline-okhttp3:0.14.1' // 网络实现层想使用okhttp3
    }

     2. 初始化Fresco

    public class MyApplication extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            Fresco.initialize(this);
        }
    }

    3. XML文件

     1) activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.xmic.view.recycleviewdemo.MainActivity">
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyview"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        </android.support.v7.widget.RecyclerView>
    </RelativeLayout>

    2)  item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="5dp"
        app:placeholderImage="@mipmap/ic_launcher">
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/sdv_img"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            fresco:fadeDuration="300"
            fresco:actualImageScaleType="focusCrop"
            fresco:retryImage="@drawable/retry"
            fresco:retryImageScaleType="centerCrop"
            fresco:progressBarImage="@drawable/retry"
            fresco:progressBarImageScaleType="centerInside"
            fresco:progressBarAutoRotateInterval="500"
            fresco:failureImage="@drawable/fault"
            fresco:failureImageScaleType="fitCenter" />
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal|bottom"
            android:layout_gravity="center"
            android:layout_below="@+id/sdv_img"
            android:layout_alignParentBottom="true"
            android:background="#cccccc"
            android:text="Image Titel"/>
    </RelativeLayout>

    3) item_list.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="50dp">
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/sdv_img"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_gravity="center"
            android:background="#aaaaaa"
            android:layout_marginLeft="10dp"
            android:layout_centerVertical="true"
            app:placeholderImage="@mipmap/ic_launcher"
            fresco:failureImage="@drawable/fault"
            fresco:failureImageScaleType="center"
            fresco:roundAsCircle="true"
            fresco:roundedCornerRadius="180dp"
            fresco:actualImageScaleType="focusCrop" />
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="20dp"
            android:layout_gravity="center"
            android:text="Image Titel"/>
    </LinearLayout>

    4. Java文件

    1) 主界面 MainActivity.java

    package com.xmic.view.recycleviewdemo;
    
    import android.app.ProgressDialog;
    import android.content.ContentResolver;
    import android.content.Context;
    import android.database.Cursor;
    import android.graphics.BitmapFactory;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.provider.MediaStore;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.GridLayoutManager;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.support.v7.widget.StaggeredGridLayoutManager;
    import android.util.Log;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.RelativeLayout;
    import android.widget.Toast;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity implements  RvAdpter.OnItemClickListener{
        private final String TAG = MainActivity.class.getSimpleName();
        private final static int SCAN_OK = 1;
        private final static int TYPE_WATERFALL = 0;
        private final static int TYPE_LISTVIEW = 1;
        private final static int TYPE_GRIDVIEW = 2;
        private RecyclerView mRecyclerView;
        private RvAdpter mAdpter;
        private ProgressDialog mProgressDialog;
        private List<Product> imageList = new ArrayList<Product>();
        RecyclerView.ItemDecoration decorator;
    
        private Handler mHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what){
                    case SCAN_OK:
                        showData();
                        break;
                }
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Log.i(TAG,"onCreate()");
            loadData();
            initView();
        }
    
        private void initView(){
            mRecyclerView = (RecyclerView) findViewById(R.id.recyview);
        }
    
        private void loadData(){
            mProgressDialog = ProgressDialog.show(this,null,"Loading...");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    ArrayList<HashMap<String,String>> pics = getAllPictures(getApplicationContext());
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inJustDecodeBounds = true;
                    if(pics != null)
                        for(int i=0; i< pics.size();i++){
                            Product item = new Product();
                            item.setId(pics.get(i).get("image_id"));
                            item.setLocalThumbPosition(pics.get(i).get("thumbnail_path"));
                            item.setProductName(pics.get(i).get("image_name"));
                            item.setLocalPosition(pics.get(i).get("image_path"));
                            BitmapFactory.decodeFile(item.getLocalPosition(), options);
                            item.setWidth(options.outWidth);
                            item.setHeight(options.outHeight);
                            item.setRatio((float)item.getWidth()/(float)item.getHeight());
                            imageList.add(item);
                        }
                    mHandler.sendEmptyMessage(SCAN_OK);
                }
            }).start();
        }
    
        public static ArrayList<HashMap<String,String>> getAllPictures(Context context) {
            ArrayList<HashMap<String,String>> picturemaps = new ArrayList<>();
            HashMap<String,String> picturemap;
            ContentResolver cr = context.getContentResolver();
            //先得到缩略图的URL和对应的图片id
            Cursor cursor = cr.query(
                    MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
                    new String[]{
                            MediaStore.Images.Thumbnails.IMAGE_ID,
                            MediaStore.Images.Thumbnails.DATA
                    },
                    null,
                    null,
                    null);
            if (cursor.moveToFirst()) {
                do {
                    picturemap = new HashMap<>();
                    picturemap.put("image_id",cursor.getInt(0)+"");
                    picturemap.put("thumbnail_path",cursor.getString(1));
                    picturemaps.add(picturemap);
                } while (cursor.moveToNext());
                cursor.close();
            }
            //再得到正常图片的path
            for (int i = 0;i<picturemaps.size();i++) {
                picturemap = picturemaps.get(i);
                String media_id = picturemap.get("image_id");
                cursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        new String[]{
                                MediaStore.Images.Media.DATA,
                                MediaStore.Images.Media.DISPLAY_NAME
                        },
                        MediaStore.Audio.Media._ID + "=" + media_id,
                        null,
                        null
                );
                if (cursor.moveToFirst()) {
                    do {
                        picturemap.put("image_path",cursor.getString(0));
                        picturemap.put("image_name",cursor.getString(1));
                        picturemaps.set(i,picturemap);
                    } while (cursor.moveToNext());
                    cursor.close();
                }
            }
            return picturemaps;
        }
    
        private void showData(){
            Log.i(TAG,"showData()");
            mProgressDialog.dismiss();
            mAdpter = new RvAdpter(MainActivity.this,imageList);
            mAdpter.setOnItemClickListener(this);
            showViewStyle(TYPE_WATERFALL);
        }
    
        private void showViewStyle(int type){
            /**
             *  用来确定每一个item如何进行排列摆放
             *  StaggeredGridLayoutManager  瀑布流
             *  LinearLayoutManager         相当于ListView的效果
             *  GridLayoutManager           相当于GridView的效果
             */
            mAdpter.setType(type);
            switch (type){
                case TYPE_WATERFALL: //瀑布流
                    mRecyclerView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT));
                    mRecyclerView.removeItemDecoration(decorator);
                    mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
                    decorator = new DividerGridItemDecoration(this);
                    mRecyclerView.addItemDecoration(decorator);
                    break;
                case TYPE_LISTVIEW: // ListView
                    mRecyclerView.removeItemDecoration(decorator);
                    mRecyclerView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT));
                    mRecyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
                    decorator = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST);
                    mRecyclerView.addItemDecoration(decorator);
                    break;
                case TYPE_GRIDVIEW: // GridView
                    mRecyclerView.removeItemDecoration(decorator);
                    mRecyclerView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT));
                    mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));
                    decorator = new DividerGridItemDecoration(this);
                    mRecyclerView.addItemDecoration(decorator);
                    break;
            }
            mRecyclerView.setAdapter(mAdpter);
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            int id = item.getItemId();
            switch (id){
                case R.id.menu_add:
                    mAdpter.addItem();
                    break;
                case R.id.menu_waterfall:
                    showViewStyle(0);
                    break;
                case R.id.menu_listview:
                    showViewStyle(1);
                    break;
                case R.id.menu_gridview:
                    showViewStyle(2);
                    break;
            }
            mAdpter.notifyDataSetChanged();
            return true;
        }
    
        @Override
        public void onItemClick(int position, Product data) {
            Log.e(TAG, "onItemClick: " + position );
            Toast.makeText(MainActivity.this,"Click: "+data.getProductName(),Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void onItemLonkClick(int position) {
            Log.e(TAG, "onItemLonkClick: " + position );
            Toast.makeText(MainActivity.this,"Remove Item: " + position,Toast.LENGTH_SHORT).show();
            mAdpter.removeItem(position);
        }
    }

    2) 适配器 RvAdapter.java

    package com.xmic.view.recycleviewdemo;
    
    import android.content.Context;
    import android.net.Uri;
    import android.support.v7.widget.RecyclerView;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    
    import com.facebook.drawee.backends.pipeline.Fresco;
    import com.facebook.drawee.drawable.ScalingUtils;
    import com.facebook.drawee.interfaces.DraweeController;
    import com.facebook.drawee.view.SimpleDraweeView;
    import com.facebook.imagepipeline.request.ImageRequest;
    
    import java.util.List;
    
    import static com.xmic.view.recycleviewdemo.R.layout.item;
    import static com.xmic.view.recycleviewdemo.R.layout.item_list;
    
    /**
     * Created by neek.chen on 2016/11/15.
     */
    
    public class RvAdpter extends RecyclerView.Adapter<RvAdpter.MyViewHolder> implements View.OnClickListener,View.OnLongClickListener{
        private Context context;
        private RecyclerView mRecyclerView;//用来计算Child位置
        private int type = 0;
        private List<Product> list;
        private OnItemClickListener onItemClickListener;
    
        public interface OnItemClickListener{
            void onItemClick(int position, Product data);
            void onItemLonkClick(int position);
        }
    
        public RvAdpter(Context context, List<Product> list){
            this.context = context;
            this.list = list;
        }
    
        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View contentView;
            if(type == 1)
                contentView = LayoutInflater.from(context).inflate(item_list,parent,false);
            else
                contentView = LayoutInflater.from(context).inflate(item,parent,false);
            contentView.setOnClickListener(this);
            contentView.setOnLongClickListener(this);
            return new MyViewHolder(contentView);
        }
    
        @Override
        public void onAttachedToRecyclerView(RecyclerView recyclerView) {
            super.onAttachedToRecyclerView(recyclerView);
            mRecyclerView = recyclerView;
        }
    
        @Override
        public void onBindViewHolder(MyViewHolder holder, final int position) {
            if(list == null)
                return;
            final Product item = list.get(position);
            if(type == 1)
                holder.title.setText(item.getProductName());
            else if(type == 0) {
    //            holder.itemView
                holder.title.setVisibility(View.GONE);
            }
            else
                holder.title.setText(position + "");
            String filePath = "file://" + Uri.parse(item.getLocalPosition());
            String fileThumbPath = "file://" + Uri.parse(item.getLocalThumbPosition());
            DraweeController control = Fresco.newDraweeControllerBuilder()
                                            .setLowResImageRequest(ImageRequest.fromUri(fileThumbPath))
    //                                      .setImageRequest(ImageRequest.fromUri(filePath))
                                            .setAutoPlayAnimations(true)
                                            .setOldController( holder.img.getController())
                                            .build();
            holder.img.setController(control);
            holder.img.setAspectRatio(item.getRatio());
        }
    
        @Override
        public int getItemCount() {
            return list == null ? 0 : list.size();
        }
    
        @Override
        public void onClick(View v) {
            int childAdapterPosition = mRecyclerView.getChildAdapterPosition(v);
            if (childAdapterPosition>= 0 && onItemClickListener!= null)
                onItemClickListener.onItemClick(childAdapterPosition,list.get(childAdapterPosition));
        }
    
        @Override
        public boolean onLongClick(View v) {
            int childAdapterPosition = mRecyclerView.getChildAdapterPosition(v);
            if (onItemClickListener!= null)
                onItemClickListener.onItemLonkClick(childAdapterPosition);
            return false;
        }
    
        public void setOnItemClickListener(OnItemClickListener onItemClickListener){
            this.onItemClickListener = onItemClickListener;
        }
    
        public void setType(int type){
            this.type = type;
        }
    
        public class MyViewHolder extends RecyclerView.ViewHolder{
            private SimpleDraweeView img;
            public TextView title;
            public MyViewHolder(View item){
                super(item);
                img = (SimpleDraweeView)item.findViewById(R.id.sdv_img);
                img.getHierarchy().setActualImageScaleType(ScalingUtils.ScaleType.FIT_XY);
                title = (TextView)item.findViewById(R.id.tv_title);
            }
        }
    
        public void addItem(){
        }
    
        public void removeItem(final int positon){
            list.remove(positon);
            notifyItemRemoved(positon);
        }
    
    }

    3) 分隔线

      采用通用的 DividerGridItemDecoration和 DividerItemDecoration

    4) 图片对象Product

       private String id;
        private String localPosition;
        private String localThumbPosition;
        private String productName;
        private int width;
        private int height;
        private float ratio;

    Fresco的各种使用场景

     引用:Android图片加载神器之Fresco,基于各种使用场景的讲解

    从网络加载一张图片

    String url = "http://xxx.jpg";
    ImageLoader.loadImage((SimpleDraweeView)findViewById(R.id.sdv_1), url);

     1. 显示一张图片

    <com.facebook.drawee.view.SimpleDraweeView
                android:id="@+id/sdv_1"
                android:layout_width="90dp"
                android:layout_height="90dp"
                app:actualImageScaleType="centerCrop"/>

    2. 显示一张圆形图片

    <com.facebook.drawee.view.SimpleDraweeView
                android:id="@+id/sdv_2"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:layout_marginTop="15dp"
                app:actualImageScaleType="centerCrop"
                app:roundAsCircle="true"/>

     3. 显示一张圆形带边框的图片

    <com.facebook.drawee.view.SimpleDraweeView
                android:id="@+id/sdv_3"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:layout_marginTop="15dp"
                app:actualImageScaleType="centerCrop"
                app:roundAsCircle="true"
                app:roundingBorderColor="#fff3cf44"
                app:roundingBorderWidth="2dp"/>

    4. 显示一张圆角图片

    <com.facebook.drawee.view.SimpleDraweeView
                android:id="@+id/sdv_4"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:layout_marginTop="15dp"
                app:actualImageScaleType="centerCrop"
                app:roundAsCircle="false"
                app:roundedCornerRadius="10dp"/>

     5. 显示一张底部是圆角的图片

    <com.facebook.drawee.view.SimpleDraweeView
                android:id="@+id/sdv_5"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:layout_marginTop="15dp"
                app:actualImageScaleType="centerCrop"
                app:roundAsCircle="false"
                app:roundedCornerRadius="10dp"
                app:roundTopLeft="false"
                app:roundTopRight="false"
                app:roundBottomLeft="true"
                app:roundBottomRight="true"/>

     6. 显示一张左上和右下是圆角的图片

    <com.facebook.drawee.view.SimpleDraweeView
                android:id="@+id/sdv_6"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:layout_marginTop="15dp"
                app:actualImageScaleType="centerCrop"
                app:roundAsCircle="false"
                app:roundedCornerRadius="10dp"
                app:roundTopLeft="true"
                app:roundTopRight="false"
                app:roundBottomLeft="false"
                app:roundBottomRight="true"/>

    7. 设置占位图

    <com.facebook.drawee.view.SimpleDraweeView
                android:id="@+id/sdv_7"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:layout_marginTop="15dp"
                app:actualImageScaleType="centerCrop"
                app:placeholderImage="@mipmap/ic_launcher"
                app:placeholderImageScaleType="centerCrop" />

     8. 带动画的显示(从半透明到不透明)

    <com.facebook.drawee.view.SimpleDraweeView
                android:id="@+id/sdv_8"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:layout_marginTop="15dp"
                app:actualImageScaleType="centerCrop"
                app:fadeDuration="3000"/>

     9. 图层叠加显示

    <com.facebook.drawee.view.SimpleDraweeView
                android:id="@+id/sdv_10"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:layout_marginTop="15dp"
                app:actualImageScaleType="centerCrop"
                app:overlayImage="@mipmap/ic_launcher"/>

     10. 其它的属性的配置,比如加载进度、加载失败、重试图

    <com.facebook.drawee.view.SimpleDraweeView
                android:id="@+id/sdv_11"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:layout_marginTop="15dp"
                app:actualImageScaleType="centerCrop"
                app:failureImage="@mipmap/ic_launcher"
                app:failureImageScaleType="centerInside"
                app:retryImage="@mipmap/ic_launcher"
                app:retryImageScaleType="centerCrop"
                app:progressBarImage="@mipmap/ic_launcher"
                app:progressBarImageScaleType="centerCrop"
                app:progressBarAutoRotateInterval="5000"/>

     11. 从本地文件(比如SDCard上)加载图片

    public static void loadFile(final SimpleDraweeView draweeView, String filePath, final int reqWidth, final int reqHeight) {
            Uri uri = new Uri.Builder()
                    .scheme(UriUtil.LOCAL_FILE_SCHEME)
                    .path(filePath)
                    .build();
            ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                    .setRotationOptions(RotationOptions.autoRotate())
                    .setLocalThumbnailPreviewsEnabled(true)
                    .setResizeOptions(new ResizeOptions(reqWidth, reqHeight))
                    .build();
            DraweeController controller = Fresco.newDraweeControllerBuilder()
                    .setImageRequest(request)
                    .setOldController(draweeView.getController())
                    .setControllerListener(new BaseControllerListener<ImageInfo>() {
                        @Override
                        public void onFinalImageSet(String id, @Nullable ImageInfo imageInfo, @Nullable Animatable anim) {
                            if (imageInfo == null) {
                                return;
                            }
    
                            ViewGroup.LayoutParams vp = draweeView.getLayoutParams();
                            vp.width = reqWidth;
                            vp.height = reqHeight;
                            draweeView.requestLayout();
                        }
                    })
                    .build();
            draweeView.setController(controller);
        }

     调用:

    ImageLoader.loadFile((SimpleDraweeView)itemView, photoInfo.thumbnailUrl, 120, 120);

     12. 从本地资源(Resources)加载图片

    public static void loadDrawable(SimpleDraweeView draweeView, int resId) {
            Uri uri = new Uri.Builder()
                    .scheme(UriUtil.LOCAL_RESOURCE_SCHEME)
                    .path(String.valueOf(resId))
                    .build();
            DraweeController controller = Fresco.newDraweeControllerBuilder()
                    .setUri(uri)
                    .setOldController(draweeView.getController())
                    .build();
            draweeView.setController(controller);
        }

     13. 对图片进行性高斯模糊处理

    public static void loadImageBlur(final SimpleDraweeView draweeView, String url) {
            loadImage(draweeView, url, new BasePostprocessor() {
                @Override
                public String getName() {
                    return "blurPostprocessor";
                }
    
                @Override
                public void process(Bitmap bitmap) {
                    BitmapBlurHelper.blur(bitmap, 35);
                }
            });
        }

    其内部调用的方法

    public static void loadImage(SimpleDraweeView simpleDraweeView, String url, BasePostprocessor processor) {
            if (TextUtils.isEmpty(url)) {
                return;
            }
    
            Uri uri = Uri.parse(url);
            ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                    .setRotationOptions(RotationOptions.autoRotate())
                    .setPostprocessor(processor)
                    .build();
            DraweeController controller = Fresco.newDraweeControllerBuilder()
                    .setImageRequest(request)
                    .setOldController(simpleDraweeView.getController())
                    .build();
            simpleDraweeView.setController(controller);
        }

     调用:

    String url = "http://xxx.jpg";
      SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1);
      simpleDraweeView.setAspectRatio(0.7f);
      ViewGroup.LayoutParams lvp = simpleDraweeView.getLayoutParams();
      lvp.width = DensityUtil.getDisplayWidth(this);
      ImageLoader.loadImageBlur(simpleDraweeView, url,
                    DensityUtil.getDisplayWidth(this), DensityUtil.getDisplayHeight(this));

     14. 未知宽高比的情况下显示图片

    String url = "http://xx.jpg";
    SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1);
    ImageLoader.loadImage(simpleDraweeView, url, new SingleImageControllerListener(simpleDraweeView));

     15. 从网络加载并显示gif格式的图片

     String url = "http://xxx.gif";
       SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv);
       ImageLoader.loadImage(simpleDraweeView, url);

     16. 加载并显示webp格式的图片

    SimpleDraweeView simpleDraweeView = (SimpleDraweeView)findViewById(R.id.sdv_1);
            ViewGroup.LayoutParams lvp = simpleDraweeView.getLayoutParams();
            lvp.width = DensityUtil.getDisplayWidth(this);
            simpleDraweeView.setAspectRatio(0.6f); // 设置宽高比
    
            ImageLoader.loadDrawable(simpleDraweeView, R.drawable.meizi_webp,
                    DensityUtil.getDisplayWidth(this), DensityUtil.getDisplayHeight(this));

    17. 从内存缓存中移除指定图片的缓存

          if (!TextUtils.isEmpty(photoInfo.originalUrl)) {
                    ImagePipeline imagePipeline = Fresco.getImagePipeline();
                    Uri uri = Uri.parse(photoInfo.originalUrl);
                    if (imagePipeline.isInBitmapMemoryCache(uri)) {
                        imagePipeline.evictFromMemoryCache(uri);
                    }
                }

     18. 从磁盘缓存中移除指定图片的缓存

        ImagePipeline imagePipeline = Fresco.getImagePipeline();
            Uri uri = Uri.parse(photoInfo.originalUrl);
            // 下面的操作是异步的
            if (imagePipeline.isInDiskCacheSync(uri)) {
                imagePipeline.evictFromDiskCache(uri);
            }

     19、清空磁盘缓存

    Fresco.getImagePipeline().clearDiskCaches();

     20、清空内存缓存

    Fresco.getImagePipeline().clearMemoryCaches();

     21、清空缓存(内存缓存 + 磁盘缓存)

    Fresco.getImagePipeline().clearCaches();

     22、在列表视图滚动时,不加载图片,等滚动停止后再开始加载图片,提升列表视图的滚动流畅度。

     // 需要暂停网络请求时调用
        public static void pause(){
            Fresco.getImagePipeline().pause();
        }
        // 需要恢复网络请求时调用
        public static void resume(){
            Fresco.getImagePipeline().resume();
        }

     23、下载图片存储到指定的路径

    /**
         * 从网络下载图片
         * 1、根据提供的图片URL,获取图片数据流
         * 2、将得到的数据流写入指定路径的本地文件
         *
         * @param url            URL
         * @param loadFileResult LoadFileResult
         */
        public static void downloadImage(Context context, String url, final DownloadImageResult loadFileResult) {
            if (TextUtils.isEmpty(url)) {
                return;
            }
    
            Uri uri = Uri.parse(url);
            ImagePipeline imagePipeline = Fresco.getImagePipeline();
            ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(uri);
            ImageRequest imageRequest = builder.build();
    
            // 获取未解码的图片数据
            DataSource<CloseableReference<PooledByteBuffer>> dataSource = imagePipeline.fetchEncodedImage(imageRequest, context);
            dataSource.subscribe(new BaseDataSubscriber<CloseableReference<PooledByteBuffer>>() {
                @Override
                public void onNewResultImpl(DataSource<CloseableReference<PooledByteBuffer>> dataSource) {
                    if (!dataSource.isFinished() || loadFileResult == null) {
                        return;
                    }
    
                    CloseableReference<PooledByteBuffer> imageReference = dataSource.getResult();
                    if (imageReference != null) {
                        final CloseableReference<PooledByteBuffer> closeableReference = imageReference.clone();
                        try {
                            PooledByteBuffer pooledByteBuffer = closeableReference.get();
                            InputStream inputStream = new PooledByteBufferInputStream(pooledByteBuffer);
                            String photoPath = loadFileResult.getFilePath();
                            Log.i("ImageLoader", "photoPath = " + photoPath);
    
                            byte[] data = StreamTool.read(inputStream);
                            StreamTool.write(photoPath, data);
                            loadFileResult.onResult(photoPath);
                        } catch (IOException e) {
                            loadFileResult.onFail();
                            e.printStackTrace();
                        } finally {
                            imageReference.close();
                            closeableReference.close();
                        }
                    }
                }
    
                @Override
                public void onFailureImpl(DataSource dataSource) {
                    if (loadFileResult != null) {
                        loadFileResult.onFail();
                    }
    
                    Throwable throwable = dataSource.getFailureCause();
                    if (throwable != null) {
                        Log.e("ImageLoader", "onFailureImpl = " + throwable.toString());
                    }
                }
            }, Executors.newSingleThreadExecutor());
        }

     调用

    String url = "http://xxx.jpg";
        String filePath = "";
        ImageLoader.downloadImage(context, url, new DownloadImageResult(filePath) {
    
            @Override
            public void onResult(String filePath) {
    
            }
    
            @Override
            public void onFail() {
    
            }
        });

     24、不使用SimpleDraweeView组件,但是想使用Fresco去加载图片(两级内存缓存+磁盘缓存要有)并显示到其他组件上(比如显示在TextView的drawableLeft属性上或者显示为View的背景)。

    public static void loadTextDrawable(final TextView view, String url, final int direction, final int iconWidth, final int iconHeight) {
            ImageLoader.loadImage(view.getContext(), url, new LoadImageResult() {
                @Override
                public void onResult(Bitmap bitmap) {
                    Drawable drawable = new BitmapDrawable(view.getContext().getResources(), bitmap);
                    final int width = DensityUtil.dipToPixels(view.getContext(), iconWidth);
                    final int height = DensityUtil.dipToPixels(view.getContext(), iconHeight);
                    drawable.setBounds(0, 0, width, height);
                    switch (direction) {
                        case 0:
                            view.setCompoundDrawables(drawable, null, null, null);
                            break;
                        case 1:
                            view.setCompoundDrawables(null, drawable, null, null);
                            break;
                        case 2:
                            view.setCompoundDrawables(null, null, drawable, null);
                            break;
                        case 3:
                            view.setCompoundDrawables(null, null, null, drawable);
                            break;
                    }  
                }
            });
        }       
  • 相关阅读:
    idea在线的ocr识别工具
    ubuntu ftp
    上海PyCon China2011大会
    Apache Mesos
    ubuntu install wxpython & ulipad
    磁力链
    魅力研习社
    黄冬 使用nc
    SVD奇异值分解
    生财有道
  • 原文地址:https://www.cnblogs.com/keyarchen/p/6063230.html
Copyright © 2011-2022 走看看