之前总结过一篇关于android加载网络图片的博客Android图片加载–妹子图客户端才用的是volley框架自带的ImageLoader,能够实现基本的图片加载,但是,同时也存在一些问题。比如上拉加载更多的时候会有明显的卡顿。最近看到一个图片加载库Glide,,据说是Google推荐使用的,作为Google脑残粉自然要学习一下。所以,在原来的基础上把基于Volley ImageLoader的部分用Glide替换。好了,废话不多说,进入正题。
因为部分代码跟以前一样,我这里就不再赘述,有兴趣的同学可以翻到前面看看。
布局文件:
大部分跟之前一样,image_item部分小改一下

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
                                    xmlns:app="http://schemas.android.com/apk/res-auto"
                                    android:layout_width="wrap_content"
                                    android:layout_height="wrap_content"
                                    app:cardBackgroundColor="#fff"
                                    app:cardCornerRadius="3dp"
                                    app:cardElevation="8dp"
                                    app:contentPadding="5dp">

    <ImageView
        android:id="@+id/iv_item_img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:scaleType="centerInside"
        android:contentDescription="@string/meizi"/>

</android.support.v7.widget.CardView>
android:adjustViewBounds=”true” 
 android:scaleType=”centerInside”


这两行非常重要,加上去之后可以实现的图片适应。

MainActivity:

public class MainActivity extends AppCompatActivity implements ImageUrlLoader.Callback, SwipeRefreshLayout.OnRefreshListener {

    private static final String TAG = "MainActivity";

    private static final int DEFAULT_IMG_COUNT = 20;//默认每页加载20张图

    private RecyclerView mRecyclerView;
    private SwipeRefreshLayout mSwipeRefreshLayout;
    private StaggeredGridLayoutManager mLayoutManager;
    private ImageAdapter mImageAdapter;
    private ImageUrlLoader imgUrlLoader;

    private List<String> imgUrlList = new ArrayList<>();

    private int mImgCount = DEFAULT_IMG_COUNT;//每页加载数
    private int nextPage = 1;
    private int[] lastPos = new int[2];

    private Animation animationIn;//进入动画
    private Animation animationOut;//退出动画

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        animationIn = AnimationUtils.loadAnimation(this,R.anim.scale_fade_in);
        animationOut = AnimationUtils.loadAnimation(this,R.anim.scale_fade_out);

        final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        //返回顶部代码  这里省略
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            }
        });

        mRecyclerView = (RecyclerView) findViewById(R.id.rv_image_list);
        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);

        //瀑布流布局
        mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setHasFixedSize(true);
        mImageAdapter = new ImageAdapter(this, imgUrlList);
        mRecyclerView.setAdapter(mImageAdapter);
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                //下拉加载更多
                mLayoutManager.findLastVisibleItemPositions(lastPos);
                if (lastPos[0] == imgUrlList.size() - 1 || lastPos[1] == imgUrlList.size() - 1 &&
                        newState == RecyclerView.SCROLL_STATE_IDLE) {
                        mSwipeRefreshLayout.setRefreshing(true);
                        imgUrlLoader.loadImageUrl(nextPage);
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                //上滑比并且按钮不可见  显示按钮
                if(dy < 0 && fab.getVisibility() == View.GONE){
                    fab.startAnimation(animationIn);
                    fab.setVisibility(View.VISIBLE);
                }
                //下滑并且按钮可见  隐藏按钮
                else if(dy > 0 && fab.getVisibility() == View.VISIBLE){
                    fab.startAnimation(animationOut);
                    fab.setVisibility(View.GONE);
                }

            }
        });

        imgUrlLoader = new ImageUrlLoader(this, mImgCount, this);
        imgUrlLoader.loadImageUrl(nextPage);

        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
        mSwipeRefreshLayout.setOnRefreshListener(this);
        mSwipeRefreshLayout.post(new Runnable() {
            @Override
            public void run() {
                mSwipeRefreshLayout.setRefreshing(true);
            }
        });
    }

    @Override
    public void addData(List<ImgData> imgDataList) {
        for (int i = 0; i < imgDataList.size(); i++) {
            imgUrlList.add(imgDataList.get(i).getUrl());
        }
        mImageAdapter.notifyDataSetChanged();
        nextPage++;

        mSwipeRefreshLayout.setRefreshing(false);
    }

    /**
     * 刷新并重置当前页数
     */
    @Override
    public void onRefresh() {
        nextPage = 1;//将页数重置为1
        imgUrlList.clear();//清空原来url数据
        imgUrlLoader.loadImageUrl(nextPage);//重置url数据
    }
}

这里跟之前的相比调整了按钮隐藏和显示的动画,并加入下拉刷新。
按钮显示隐藏效果:
scale_fade_in

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha
        android:duration="300"
        android:fromAlpha="0.0"
        android:toAlpha="1.0"/>

    <scale
        android:duration="300"
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0"/>
</set>

scale_fade_out

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <alpha
        android:duration="300"
        android:fromAlpha="1.0"
        android:toAlpha="0"/>

    <scale
        android:duration="300"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="0.0"
        android:toYScale="0.0"/>
</set>

下面是最重要的部分,适配器:
ImageAdapter:

public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ImageViewHolder> {

    private static final String TAG = "ImageAdapter";

    private Context context;
    private List<String> imgUrlList;

    public ImageAdapter(Context context, List<String> imgUrlList) {
        this.context = context;
        this.imgUrlList = imgUrlList;
    }

    @Override
    public ImageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.image_item,null);
        return new ImageViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ImageViewHolder holder, int position) {

        Glide.with(context)
                .load(imgUrlList.get(position))
                .crossFade()
                .into(holder.imageView);
    }

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

    class ImageViewHolder extends RecyclerView.ViewHolder {

        ImageView imageView;

        public ImageViewHolder(View itemView) {
            super(itemView);
            imageView = (ImageView) itemView.findViewById(R.id.iv_item_img);
        }
    }
}

可以明显的看出来,强大的Glide仅仅用了几句话就能实现图片的加载,我和我的小伙伴都惊呆了,而且重要的是加载的效果非常好,不会出现卡顿(至少在我自己手机上调试的时候没有出现卡顿情况),滑动的效果如丝般顺滑,比之前的Volley好多了。

总结:

图片加载效果基本能够实现,而且比原先的好多了,但是这仅仅只是最基本的用法,作为Google推荐使用的开源库,自然有他的过人之处,还需要花时间去学习。
以上仅仅实现最基本的加载和显示网络图片,还有很多值得改进和优化的地方,比如图片缓存,滑动的时候取消图片加载提高滑动的流畅度和效率等,还有Glide和Volley,okhttp等框架的结合,Glide的学习之路还很漫长,以后有时间继续分享。
最后再说点题外话,开源的框架确实是非常好用的东西。各路大神将开发中经常使用的东西封装好提供给开发者,节约了很多的开发时间。从最开始的时候什么都不懂,每次网络请求都自己写HttpURLconnection来连接网络,一个项目中有太多的重复代码。到后来接触到Volley,还有现在的Glide等框架,工程中代码精简了不少,不得不感慨一个好的框架有多重要,怪不得Spring能够给Web程序员带来春天。当然,使用框架仅仅是最基本的部分。仅仅掌握如何使用框架是远远不够的,时代在变,今天的框架说不定明天就被别的取代了,今天的Spring可能在明天就被Summer取代了。大部分优秀的框架都是开源的,所以,在使用的基础上有必要去研究源码,学习大神的编码风格和编程技术,最后编写自己的框架。想要成为优秀的程序员还有很长的路要走。