Android Open Source - apps-android-commons Media Wiki Image View






From Project

Back to project page apps-android-commons.

License

The source code is released under:

Apache License

If you think the Android project apps-android-commons listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * Copyright (C) 2013 The Android Open Source Project
 *//from ww w.j  a  v  a  2  s.co m
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.wikimedia.commons;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.BitmapDrawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;

import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageContainer;
import com.android.volley.toolbox.ImageLoader.ImageListener;
import org.wikimedia.commons.contributions.Contribution;
import org.wikimedia.commons.contributions.ContributionsContentProvider;


public class MediaWikiImageView extends ImageView {

    private Media mMedia;

    private ImageLoader mImageLoader;

    private ImageContainer mImageContainer;

    private View loadingView;

    private boolean isThumbnail;

    public MediaWikiImageView(Context context) {
        this(context, null);
    }

    public MediaWikiImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        TypedArray actualAttrs = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MediaWikiImageView, 0, 0);
        isThumbnail = actualAttrs.getBoolean(0, false);
        actualAttrs.recycle();
    }

    public MediaWikiImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setMedia(Media media, ImageLoader imageLoader) {
        this.mMedia = media;
        mImageLoader = imageLoader;
        loadImageIfNecessary(false);
    }

    public void setLoadingView(View loadingView) {
        this.loadingView = loadingView;
    }

    public View getLoadingView() {
        return loadingView;
    }

    private void loadImageIfNecessary(final boolean isInLayoutPass) {
        loadImageIfNecessary(isInLayoutPass, false);
    }

    private void loadImageIfNecessary(final boolean isInLayoutPass, final boolean tryOriginal) {
        int width = getWidth();
        int height = getHeight();

        // if the view's bounds aren't known yet, hold off on loading the image.
        if (width == 0 && height == 0) {
            return;
        }

        if(mMedia == null) {
            return;
        }


        // Do not count for density when loading thumbnails.
        // FIXME: Use another 'algorithm' that doesn't punish low res devices
        if(isThumbnail) {
            float dpFactor =  Math.max(getResources().getDisplayMetrics().density, 1.0f);
            width = (int) (width / dpFactor);
            height = (int) (height / dpFactor);
        }

        final String  mUrl;
        if(tryOriginal) {
            mUrl = mMedia.getImageUrl();
        } else {
            // Round it to the nearest 320
            // Possible a similar size image has already been generated.
            // Reduces Server cache fragmentation, also increases chance of cache hit
            // If width is less than 320, we round up to 320
            int bucketedWidth = width <= 320 ? 320 : Math.round((float)width / 320.0f) * 320;
            if(mMedia.getWidth() != 0 && mMedia.getWidth() < bucketedWidth) {
                // If we know that the width of the image is lesser than the required width
                // We don't even try to load the thumbnai, go directly to the source
                loadImageIfNecessary(isInLayoutPass, true);
                return;
            } else {
                mUrl = mMedia.getThumbnailUrl(bucketedWidth);
            }
        }

        // if the URL to be loaded in this view is empty, cancel any old requests and clear the
        // currently loaded image.
        if (TextUtils.isEmpty(mUrl)) {
            if (mImageContainer != null) {
                mImageContainer.cancelRequest();
                mImageContainer = null;
            }
            setImageBitmap(null);
            return;
        }

        // Don't repeat work. Prevents onLayout cascades
        // We ignore it if the image request was for either the current URL of for the full URL
        // Since the full URL is always the second, and
        if (mImageContainer != null && mImageContainer.getRequestUrl() != null) {
            if (mImageContainer.getRequestUrl().equals(mMedia.getImageUrl()) || mImageContainer.getRequestUrl().equals(mUrl)) {
                return;
            } else {
                // if there is a pre-existing request, cancel it if it's fetching a different URL.
                mImageContainer.cancelRequest();
                BitmapDrawable actualDrawable = (BitmapDrawable)getDrawable();
                if(actualDrawable != null && actualDrawable.getBitmap() != null) {
                    setImageBitmap(null);
                    if(loadingView != null) {
                        loadingView.setVisibility(View.VISIBLE);
                    }
                }
            }
        }

        // The pre-existing content of this view didn't match the current URL. Load the new image
        // from the network.
        ImageContainer newContainer = mImageLoader.get(mUrl,
                new ImageListener() {
                    @Override
                    public void onErrorResponse(final VolleyError error) {
                        if(!tryOriginal) {
                            post(new Runnable() {
                                public void run() {
                                    loadImageIfNecessary(false, true);
                                }
                            });
                        }

                    }

                    @Override
                    public void onResponse(final ImageContainer response, boolean isImmediate) {
                        // If this was an immediate response that was delivered inside of a layout
                        // pass do not set the image immediately as it will trigger a requestLayout
                        // inside of a layout. Instead, defer setting the image by posting back to
                        // the main thread.
                        if (isImmediate && isInLayoutPass) {
                            post(new Runnable() {
                                @Override
                                public void run() {
                                    onResponse(response, false);
                                }
                            });
                            return;
                        }

                        if (response.getBitmap() != null) {
                            setImageBitmap(response.getBitmap());
                            if(tryOriginal && mMedia instanceof Contribution && (response.getBitmap().getWidth() > mMedia.getWidth() || response.getBitmap().getHeight() > mMedia.getHeight())) {
                                // If there is no width information for this image, save it. This speeds up image loading massively for smaller images
                                mMedia.setHeight(response.getBitmap().getHeight());
                                mMedia.setWidth(response.getBitmap().getWidth());
                                ((Contribution)mMedia).setContentProviderClient(MediaWikiImageView.this.getContext().getContentResolver().acquireContentProviderClient(ContributionsContentProvider.AUTHORITY));
                                ((Contribution)mMedia).save();
                            }
                            if(loadingView != null) {
                                loadingView.setVisibility(View.GONE);
                            }
                        } else {
                            // I'm not really sure where this would hit but not onError
                        }
                    }
                });

        // update the ImageContainer to be the new bitmap container.
        mImageContainer = newContainer;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        loadImageIfNecessary(true);
    }

    @Override
    protected void onDetachedFromWindow() {
        if (mImageContainer != null) {
            // If the view was bound to an image request, cancel it and clear
            // out the image from the view.
            mImageContainer.cancelRequest();
            setImageBitmap(null);
            // also clear out the container so we can reload the image if necessary.
            mImageContainer = null;
        }
        super.onDetachedFromWindow();
    }

    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        invalidate();
    }
}




Java Source Code List

com.gst_sdk.GStreamer.java
com.gst_sdk.GStreamer.java
org.wikimedia.commons.AboutActivity.java
org.wikimedia.commons.CommonsApplication.java
org.wikimedia.commons.EventLog.java
org.wikimedia.commons.HandlerService.java
org.wikimedia.commons.LicenseList.java
org.wikimedia.commons.License.java
org.wikimedia.commons.MediaDataExtractor.java
org.wikimedia.commons.MediaWikiImageView.java
org.wikimedia.commons.Media.java
org.wikimedia.commons.Prefs.java
org.wikimedia.commons.SettingsActivity.java
org.wikimedia.commons.Utils.java
org.wikimedia.commons.WelcomeActivity.java
org.wikimedia.commons.api.MWApi.java
org.wikimedia.commons.auth.AuthenticatedActivity.java
org.wikimedia.commons.auth.LoginActivity.java
org.wikimedia.commons.auth.WikiAccountAuthenticatorService.java
org.wikimedia.commons.auth.WikiAccountAuthenticator.java
org.wikimedia.commons.campaigns.CampaignActivity.java
org.wikimedia.commons.campaigns.CampaignContribution.java
org.wikimedia.commons.campaigns.Campaign.java
org.wikimedia.commons.campaigns.CampaignsContentProvider.java
org.wikimedia.commons.campaigns.CampaignsListAdapter.java
org.wikimedia.commons.campaigns.CampaignsSyncAdapter.java
org.wikimedia.commons.campaigns.CampaignsSyncService.java
org.wikimedia.commons.category.CategorizationFragment.java
org.wikimedia.commons.category.CategoryContentProvider.java
org.wikimedia.commons.category.Category.java
org.wikimedia.commons.contributions.ContributionController.java
org.wikimedia.commons.contributions.ContributionViewHolder.java
org.wikimedia.commons.contributions.Contribution.java
org.wikimedia.commons.contributions.ContributionsActivity.java
org.wikimedia.commons.contributions.ContributionsContentProvider.java
org.wikimedia.commons.contributions.ContributionsListAdapter.java
org.wikimedia.commons.contributions.ContributionsListFragment.java
org.wikimedia.commons.contributions.ContributionsSyncAdapter.java
org.wikimedia.commons.contributions.ContributionsSyncService.java
org.wikimedia.commons.contributions.MediaListAdapter.java
org.wikimedia.commons.data.DBOpenHelper.java
org.wikimedia.commons.media.CategoryImagesLoader.java
org.wikimedia.commons.media.MediaDetailFragment.java
org.wikimedia.commons.media.MediaDetailPagerFragment.java
org.wikimedia.commons.media.MediaDetailSpacer.java
org.wikimedia.commons.modifications.CategoryModifier.java
org.wikimedia.commons.modifications.ModificationsContentProvider.java
org.wikimedia.commons.modifications.ModificationsSyncAdapter.java
org.wikimedia.commons.modifications.ModificationsSyncService.java
org.wikimedia.commons.modifications.ModifierSequence.java
org.wikimedia.commons.modifications.PageModifier.java
org.wikimedia.commons.modifications.TemplateRemoveModifier.java
org.wikimedia.commons.upload.MultipleShareActivity.java
org.wikimedia.commons.upload.MultipleUploadListFragment.java
org.wikimedia.commons.upload.ShareActivity.java
org.wikimedia.commons.upload.SingleUploadFragment.java
org.wikimedia.commons.upload.UploadController.java
org.wikimedia.commons.upload.UploadService.java