0

I'm experiencing some choppyness when loading bitmaps into ImageViews from an AsyncTask.

I have a fragment in which I display information loaded from SQLite, and said information often times have photos attached. When my fragment is launched, it takes up to a second before it is displayed (the app appears to hang for a bit), probably because of the heavy data loading, which tells me I might be doing something wrong.

Here is a stripped down version of my implementation:

public class InformationFragment extends Fragment {
    private ArrayList<MyPhoto> mPhotos;
    private LinearLayout mPhotoContainer;
    private View mView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        // ....

        mView = inflater.inflate(R.layout.fragment_information, container, false);
        mPhotoContainer = (LinearLayout) mView.findViewById(R.id.fragment_information_photos_container);

        return mView;
    }

    @Override
    public void onResume() {
        super.onResume();
        loadInformation();
    }

    private void loadInformation() {
        // Loads information from database and puts it into TextViews and such.
        // Relatively performance heavy operations, should perhaps run off main, but it's not the cause
        // of my problems as it was pretty smooth before I implemented photo attachments
    }

    private ArrayList<MyPhoto> getPhotos() {
        // Loads photos from database. Not sure but could be pretty performance heavy, you tell me :)
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        if(mPhotoContainer.getChildCount() == 0) {
            mPhotos = getPhotos();

            for (MyPhoto p : mPhotos) {
                addImageViewForPhoto(p);
            }
        }
    }

    private void addImageViewForPhoto(MyPhoto p) {
        final ImageView iv = new ImageView(getActivity());

        mPhotoContainer.addView(iv);

        new MyPhotoLoaderTask(iv).execute(p.getBytes());
    }

}

The following is the MyPhotoLoaderTask class

public class MyPhotoLoaderTask extends AsyncTask<byte[], Void, Bitmap> {

    private final WeakReference<ImageView> mWeakImageView;

    public MyPhotoLoaderTask(ImageView iv) {
        mWeakImageView = new WeakReference<ImageView>(iv);
    }

    @Override
    protected Bitmap doInBackground(byte[]... params) {
        return MyPhotoUtils.createBitmap(params[0], 100, 100);
    }

    @Override
    protected void onPostExecute(final Bitmap result) {
        if(mWeakImageView != null && result != null) {
            final ImageView iv = mWeakImageView.get();
            iv.setImageBitmap(result);
        }
    }
}

And lastly, the MyPhotoUtils.createBitmap() method

public static Bitmap createBitmap(byte[] bytes, int reqWidth, int reqHeight) {
    BitmapFactory.Options opts = new BitmapFactory.Options();

    opts.inJustDecodeBounds = true;
    BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts);

    opts.inSampleSize = getInSampleSize(opts, reqWidth, reqHeight);
    opts.inJustDecodeBounds = false;

    return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts);
}

I don't mind the fact that loading the images takes a while, but I would love for the fragment to load with all of the text information already present, and then have the images appear one by one after the user has begun interaction with the fragment. The current situation is pretty bad in my opinion, and I fear it will become even worse if the user will attach even more photos to the information.

4

0 回答 0