androidandroid-support-libraryandroid-gridviewlegacy-app

Android; setAdapter working/not working depending on android support library version


I currently have a small legacy app which shows the current albums and their images in different views. So view one shows the albums, upon selecting an album it opens the view that shows the images of the selected album.

When the app is running with the android support library version 18 the apps works fine. But when I upgrade the version to 19 or higher the app stops working correctly. It opens the view that supposed to show the albums but it does not actually show the albums. See the end of the post for images that illustrate the problem.

I have pinpointed the problem to the following line of code.

mBucketAdapter = new BucketGridAdapter(getActivity(), 0, buffer, false);
mGridView.setAdapter(mBucketAdapter); <---------

The BucketGridAdapteris a custom class that extends ArrayAdapter<BucketEntry>. As you can see, the class BucketGridAdapter has a override for the function getView. This function is getting called on android support library version 18 but when I upgrade the version it does not get called anymore.

I have noticed that when I comment out the line mGridView.setAdapter(mBucketAdapter); it shows the same behavior as when I upgrade the version of the android support library. (empty grid)

The problem is that I am not able to debug between this line of code mGridView.setAdapter(mBucketAdapter) and the function getView() so I do not know why the getView function is not called on a higher version of the android support library.

I would love to have some help with this problem. If you are missing any information just say so, and I will add it.

EDIT: Note that get count has values on android support library version 19 and higher so thegetView function should be called.

mBucketAdapter = new BucketGridAdapter(getActivity(), 0, buffer, false);
int count = mBucketAdapter.getCount(); // <-- count = 8
mGridView.setAdapter(mBucketAdapter);

See BucketImageFragment class below:

package mediachooser.fragment;

import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.ImageColumns;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.Toast;
import com.synconset.FakeR;
import mediachooser.BucketEntry;
import mediachooser.MediaChooserConstants;
import mediachooser.activity.HomeFragmentActivity;
import mediachooser.adapter.BucketGridAdapter;

import java.util.ArrayList;

public class BucketImageFragment extends Fragment{

    // The indices should match the following projections.
    private final int INDEX_BUCKET_ID     = 0;
    private final int INDEX_BUCKET_NAME   = 1;
    private final int INDEX_BUCKET_URL    = 2;

    private static final String[] PROJECTION_BUCKET = {
        ImageColumns.BUCKET_ID,
        ImageColumns.BUCKET_DISPLAY_NAME,
        ImageColumns.DATA};

    private View mView;
    private GridView mGridView;
    private BucketGridAdapter mBucketAdapter;

    private Cursor mCursor;



    public BucketImageFragment(){
        setRetainInstance(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if(mView == null){
            mView     = inflater.inflate(getRLayoutId("view_grid_layout_media_chooser"), container, false);
            mGridView = (GridView)mView.findViewById(getRIntId("gridViewFromMediaChooser"));
            init();
        }else{
            ((ViewGroup) mView.getParent()).removeView(mView);
            if(mBucketAdapter == null){
                Toast.makeText(getActivity(), getActivity().getString(getRStringId("no_media_file_available")), Toast.LENGTH_SHORT).show();
            }
        }
        return mView;
    }


    private void init(){
        final String orderBy = MediaStore.Images.Media.DATE_TAKEN;
         mCursor = getActivity().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, PROJECTION_BUCKET, null, null, orderBy + " DESC");
        ArrayList<BucketEntry> buffer = new ArrayList<BucketEntry>();
        try {
            while (mCursor.moveToNext()) {
                BucketEntry entry = new BucketEntry(
                        mCursor.getInt(INDEX_BUCKET_ID),
                        mCursor.getString(INDEX_BUCKET_NAME),mCursor.getString(INDEX_BUCKET_URL));

                if (! buffer.contains(entry)) {
                    buffer.add(entry);
                }
            }

            if(mCursor.getCount() > 0){
                mBucketAdapter = new BucketGridAdapter(getActivity(), 0, buffer, false);
                mGridView.setAdapter(mBucketAdapter); <------- THIS LINE
            }else{
                Toast.makeText(getActivity(), getActivity().getString(getRStringId("no_media_file_available")), Toast.LENGTH_SHORT).show();
            }

            mGridView.setOnItemClickListener(new OnItemClickListener() {

                @Override
                public void onItemClick(AdapterView<?> adapter, View view,
                        int position, long id) {

                    BucketEntry bucketEntry  = (BucketEntry)adapter.getItemAtPosition(position);
                    Intent selectImageIntent = new Intent(getActivity(),HomeFragmentActivity.class);
                    selectImageIntent.putExtra("name", bucketEntry.bucketName);
                    selectImageIntent.putExtra("image", true);
                    selectImageIntent.putExtra("isFromBucket", true);
                    getActivity().startActivityForResult(selectImageIntent, MediaChooserConstants.BUCKET_SELECT_IMAGE_CODE);
                }
            });

        } finally {
            mCursor.close();
        }
    }

    public BucketGridAdapter getAdapter() {
        return  mBucketAdapter;
    }


    public int getRStringId(String resourceId){
        return FakeR.getId(getActivity(), "string", resourceId);
    }

    public int getRIntId(String resourceId){
        return FakeR.getId(getActivity(), "id", resourceId);
    }

    public int getRColorId(String resourceId){
        return FakeR.getId(getActivity(), "color", resourceId);
    }

    public int getRDrawableId(String resourceId){
        return FakeR.getId(getActivity(), "drawable", resourceId);
    }
    public int getRLayoutId(String resourceId){
        return FakeR.getId(getActivity(), "layout", resourceId);
    }


}

See BucketGridAdapter class below.

package mediachooser.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.synconset.FakeR;
import mediachooser.BucketEntry;
import mediachooser.MediaChooserConstants;
import mediachooser.async.ImageLoadAsync;
import mediachooser.async.MediaAsync;

import java.util.ArrayList;

public class BucketGridAdapter extends ArrayAdapter<BucketEntry> {

//  public BucketVideoFragment bucketVideoFragment;

    private Context mContext;
    private ArrayList<BucketEntry> mBucketEntryList;
    private boolean mIsFromVideo;
    private int mWidth;
    LayoutInflater viewInflater;


    public BucketGridAdapter(Context context, int resource, ArrayList<BucketEntry> categories, boolean isFromVideo) {
        super(context, resource, categories);
        mBucketEntryList = categories;
        mContext         = context;
        mIsFromVideo     = isFromVideo;
        viewInflater = LayoutInflater.from(mContext);
    }

    public int getCount() {
        return mBucketEntryList.size();
    }

    @Override
    public BucketEntry getItem(int position) {
        return mBucketEntryList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public void addLatestEntry(String url) {
        int count = mBucketEntryList.size();
        boolean success = false;
        for(int i = 0; i< count; i++){
            if(mBucketEntryList.get(i).bucketName.equals(MediaChooserConstants.folderName)){
                mBucketEntryList.get(i).bucketUrl = url;
                success = true;
                break;
            }
        }

        if(!success){
            BucketEntry latestBucketEntry = new BucketEntry(0, MediaChooserConstants.folderName, url);
            mBucketEntryList.add(0, latestBucketEntry);
        }
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder;

        if (convertView == null) {

            mWidth = mContext.getResources().getDisplayMetrics().widthPixels;

            convertView  = viewInflater.inflate(getRLayoutId("view_grid_bucket_item_media_chooser"), parent, false);

            holder = new ViewHolder();
            holder.imageView    = (ImageView) convertView.findViewById(getRIntId("imageViewFromMediaChooserBucketRowView"));
            holder.nameTextView = (TextView) convertView.findViewById(getRIntId("nameTextViewFromMediaChooserBucketRowView"));

            convertView.setTag(holder);

        }else{
            holder = (ViewHolder) convertView.getTag();
        }

        FrameLayout.LayoutParams imageParams = (FrameLayout.LayoutParams) holder.imageView.getLayoutParams();
        imageParams.width  = mWidth/3;
        imageParams.height = mWidth/3;

        holder.imageView.setLayoutParams(imageParams);

        if(mIsFromVideo){
//          new VideoLoadAsync(bucketVideoFragment, holder.imageView, false, mWidth/2).executeOnExecutor(MediaAsync.THREAD_POOL_EXECUTOR, mBucketEntryList.get(position).bucketUrl.toString());

        }else{
            ImageLoadAsync loadAsync = new ImageLoadAsync(mContext, holder.imageView, mWidth/2);
            loadAsync.executeOnExecutor(MediaAsync.THREAD_POOL_EXECUTOR, mBucketEntryList.get(position).bucketUrl);
        }

        holder.nameTextView.setText(mBucketEntryList.get(position).bucketName );
        return convertView;
    }

    class ViewHolder {
        ImageView imageView;
        TextView nameTextView;
    }

    public int getRStringId(String resourceId){
        return FakeR.getId(mContext, "string", resourceId);
    }

    public int getRIntId(String resourceId){
        return FakeR.getId(mContext, "id", resourceId);
    }

    public int getRColorId(String resourceId){
        return FakeR.getId(mContext, "color", resourceId);
    }

    public int getRDrawableId(String resourceId){
        return FakeR.getId(mContext, "drawable", resourceId);
    }
    public int getRLayoutId(String resourceId){
        return FakeR.getId(mContext, "layout", resourceId);
    }

}

See BucketEntry class below

package mediachooser;

public class BucketEntry {
    public String bucketName;
    public int bucketId;
    public String bucketUrl = null;

    public BucketEntry(int id, String name, String url) {
        bucketId = id;
        bucketName = ensureNotNull(name);
        bucketUrl = url;
    }

    @Override
    public int hashCode() {
        return bucketId;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof BucketEntry)) return false;
        BucketEntry entry = (BucketEntry) object;
        return bucketId == entry.bucketId;
    }

    public static String ensureNotNull(String value) {
        return value == null ? "" : value;
    }
}

See view_grid_layout_media_chooser.xml view below

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_height="fill_parent"
              android:layout_width="fill_parent"
              android:orientation="vertical" > <!-- android:background="@drawable/image_bg" -->

    <GridView
            android:id="@+id/gridViewFromMediaChooser"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:columnWidth="0dip"
            android:fadingEdgeLength="10dip"
            android:fastScrollEnabled="true"
            android:gravity="center"
            android:horizontalSpacing="2dip"
            android:numColumns="3"
            android:requiresFadingEdge="vertical"
            android:scrollingCache="true"
            android:stretchMode="columnWidth"
            android:verticalSpacing="2dip" />

</LinearLayout>

See view_grid_bucket_item_media_chooser.xml view below

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <mediachooser.SquareImageView
        android:id="@+id/imageViewFromMediaChooserBucketRowView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@null"
        android:contentDescription="@null"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_loading" />

    <TextView
        android:id="@+id/nameTextViewFromMediaChooserBucketRowView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="#88666666"
        android:ellipsize="end"
        android:gravity="center"
        android:maxLines="1"
        android:text="@string/video"
        android:textColor="@android:color/white"
        android:textSize="14sp" />

</FrameLayout>

Illustration images:

Working:

http://i.imgur.com/WnLAhL1.png

Not working:

http://i.imgur.com/jObA7ps.png


Solution

  • OK, After looking for hours and hours and..... more hours we found a little view XML setting that messed up the visibility of one of the views.

    android:visibility="gone"
    

    It seems like this XML setting got ignored by the Android Support Library version 18 but when it was upgraded to a higher version the settings was used.

    When a view is hidden, either by above setting or by wrong width en height settings, android does not bother to start writing the view. Or with other words; use the getView function, which it did not execute in our case when using 19 or higher version of the Android Support Library.

    Hope it helps someone.