Recently, ImageSwitcher
was used in the project to switch between images. It is very simple to use, but it was found that when the image size was large (more than 3M), the program crashed due to memory overflow (OOM).
The reason is that the picture is too large, and when it is displayed on ImageView
, the memory is not enough. However, there are several well-known image libraries in the industry that have solved the problem of memory overflow when loading large images. Among them, picasso developed by square company and Glide developed by bumptech are more famous. These two libraries are excellent and have their own advantages (about For a comparison of these two libraries, please refer to: http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0327/2650.html).
So how to make ImageSwitcher
work with Picasso
?
In terms of layout, just make the background of ImageSwitcher
transparent, then put an ImageView
behind it, and then use ImageSwitcher
to make left and right sliding effects, and then The actual display of the picture uses the ImageView
behind it.
The layout is as follows:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="@string/loading" /> <ImageView android:id="@ + id/ivShow" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/transparent" android:contentDescription="@string/empty" android:scaleType="centerInside" /> <ImageSwitcher android:id="@ + id/isShowImages" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:color/transparent" /> </RelativeLayout>
About how to use Picasso
, I won’t say much here, please refer to the official instructions. There are two points to note here:
1. makeView
in the implementation of ImageSwitcher
should be set as a transparent background
2. Picasso
needs to call fit()
and centerCrop()
to adjust the image size, thus greatly saving memory
The key code is as follows:
public class ShowImageActivity extends AppCompatActivity implements ViewSwitcher.ViewFactory, View.OnTouchListener { private static final String TAG = "ShowImageActivity"; private ImageSwitcher mImageSwitcher; private ImageView mIvShow; private String mFolderPath; private List<String> mImagePaths = new ArrayList<>(); private int mCurrentPosition = 0; private File mCurrentImageFile; private float mDownX; private final Handler mHandler = new MyHandler(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R. layout. activity_show_image); mImageSwitcher = (ImageSwitcher) findViewById(R.id.isShowImages); mImageSwitcher.setFactory(this); mImageSwitcher.setOnTouchListener(this); mIvShow = (ImageView) findViewById(R.id.ivShow); mFolderPath = "The path of the folder where the picture is located"; loadData(); } private void loadData() { new Thread(new Runnable() { @Override public void run() { File dir = new File(mFolderPath); if (dir. exists()) { File[] images = dir. listFiles(); if (images. length > 0) { for (int i = 0, j = images. length; i < j; i ++ ) { File pic = images[i]; if (pic. isDirectory()) { continue; } mImagePaths.add(pic.getAbsolutePath()); } } } mHandler.obtainMessage().sendToTarget(); } }).start(); } private void handleMessage(Message msg) { if (msg. what == 1) { if (mCurrentImageFile != null) { Picasso.with(this) .load(mCurrentImageFile) .fit() .centerCrop() .into(mIvShow); } } else { if (mImagePaths. size() == 0) { finish(); } else { showPicture(); } } } private void showPicture() { new Thread(new Runnable() { @Override public void run() { String imagePath = mImagePaths. get(mCurrentPosition); mCurrentImageFile = new File(imagePath); mHandler.obtainMessage(1).sendToTarget(); } }).start(); } @Override public View makeView() { final ImageView i = new ImageView(this); i.setBackgroundColor(Color.TRANSPARENT); return i; } @Override public boolean onTouch(View v, MotionEvent event) { switch (event. getAction()) { case MotionEvent. ACTION_DOWN: { //The X coordinate of the finger pressed mDownX = event. getX(); break; } case MotionEvent. ACTION_UP: { float lastX = event. getX(); //When the X coordinate is greater than when it is lifted, it will display the previous picture if (lastX > mDownX) { if (mCurrentPosition > 0) { // set animation mImageSwitcher.setInAnimation(AnimationUtils.loadAnimation(getApplication(), R.anim.left_in)); mImageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(getApplication(), R.anim.right_out)); mCurrentPosition--; showPicture(); } } if (lastX < mDownX) { if (mCurrentPosition < mImagePaths. size() - 1) { mImageSwitcher.setInAnimation(AnimationUtils.loadAnimation(getApplication(), R.anim.right_in)); mImageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(getApplication(), R.anim.left_out)); mCurrentPosition++; showPicture(); } } } break; } return true; } private static class MyHandler extends Handler { private final WeakReference<ShowImageActivity> mActivity; public MyHandler(ShowImageActivity activity) { mActivity = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { ShowImageActivity activity = mActivity. get(); if (activity != null) { activity. handleMessage(msg); } } } }
Note: Some logic codes that are not relevant to this article have been removed.
The usage part of ImageSwitcher
refers to: http://blog.csdn.net/xiaanming/article/details/8988152
At present, this solution can solve the OOM problem, but the effect of sliding is gone, and it will be optimized later.