之前总结过一篇关于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取代了。大部分优秀的框架都是开源的,所以,在使用的基础上有必要去研究源码,学习大神的编码风格和编程技术,最后编写自己的框架。想要成为优秀的程序员还有很长的路要走。