ArrayAdapter<>没有在onPause(),android中清除

时间:2015-03-23 21:00:22

标签: android android-fragments android-arrayadapter android-gridview android-sdcard

我一直在研究这个问题,但没有。我的ArrayAdapter<>的{​​{1}}位于GridView标签中。我得出结论,因为它是一个片段,当我浏览标签然后返回我的照片标签,而不是从头重新上传图像,而是上传图像并将相同的图像添加到适配器。这导致了2组相同的图像,但我需要的只是在重新访问选项卡时上传的一组。

我尝试将Fragment后跟adapter.clear()放入我的adapter.notifyDataSetChanged()片段生命周期方法。因此,当片段不再可见时,所有适配器项目都会清除,当片段再次可见时,它会从我的SD卡中加载新的图像副本。但这不起作用,除了先前加载的集合之外,它仍然添加了新的图像集。任何人都知道如何清除适配器,所以每次重新访问选项卡时都不会添加相同的图像?或者,如果有其他方法可以做到这一点,我不知道......提前致谢。

更新

感谢所有人的贡献,我终于找到了一个有用的工作。我在不同的阶段记录了所有onPause()个变量,发现无论我在哪里清除它,它总是会在adapter方法中发布一个重复集,所以它一定是来自那里。所以我只是在我的适配器上做了一个条件,以防止它再次加载。我注意到我的适配器在从其他选项卡返回后已经加载,使用loadSDCard()。这来自我的getCount(),是缺失的部分:

PhotoTab.java

更新2:

请参阅下面的答案,我发现了重复项首先发生的真正原因。

enter image description here

PhotoTab.java

if (adapter.getCount() == 0) {
            adapter.addAll(loadSDCard());

            // add the default icons remaining, to GridView, if less than 24 files on SD card
            for (int i = 0; i < (24 - photoList.size()); i++) {

                adapter.add(new PhotoGridItem(BitmapFactory.decodeResource(getResources(),
                        R.drawable.ic_photo_placeholder)));
            }

        }

GridViewPhotoAdapter

package org.azurespot.cutecollection;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.GridView;

import org.azurespot.R;

import java.io.File;
import java.util.ArrayList;

/**
 * Created by mizu on 2/8/15.
 */
public class PhotoTab extends Fragment {

    private GridView gridView;
    File[] files;
    ArrayList<PhotoGridItem> photoList = new ArrayList<>();
    ArrayAdapter<PhotoGridItem> adapter;
    Bitmap bitmap;

    public PhotoTab() {
        super();
    }

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

        // Inflate the layout for this fragment
        View v = inflater.inflate(R.layout.photo_tab, container, false);

        // with fragments, make sure you include the rootView when finding id
        gridView = (GridView) v.findViewById(R.id.photo_grid);
        adapter = new GridViewPhotoAdapter(getActivity(), R.layout.photo_grid_item);
        // Set the Adapter to GridView
        gridView.setAdapter(adapter);
        adapter.addAll(loadSDCard());

        // add the default icons remaining, to GridView, if less than 24 files on SD card
        for (int i = 0; i < (24 - photoList.size()); i++) {

            adapter.add(new PhotoGridItem(BitmapFactory.decodeResource(getResources(),
                    R.drawable.ic_photo_placeholder)));
        }

        return v;
    }


    private ArrayList<PhotoGridItem> loadSDCard() {

        try {
            // gets directory CutePhotos from sd card
            File cutePhotosDir = new File(Environment.getExternalStoragePublicDirectory
                    (Environment.DIRECTORY_PICTURES), "CutePhotos");
            // lists all files in CutePhotos, loads in Files[] array
            files = cutePhotosDir.listFiles();

            for (File singleFile : files) {
                String filePath = singleFile.getAbsolutePath();

                // this method makes size small for the view (to save memory)
                bitmap = decodeSampledBitmap(filePath, 270, 270);

                photoList.add(new PhotoGridItem(bitmap));
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return photoList;
    }

    public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

    public static Bitmap decodeSampledBitmap(String path, int reqWidth, int reqHeight) {

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;

        return BitmapFactory.decodeFile(path, options);
    }

    @Override
    public void onPause(){
        super.onPause();
        adapter.clear();
        adapter.notifyDataSetChanged();

    }

}

PhotoGridItem

    package org.azurespot.cutecollection;

/**
* Created by mizu on 2/5/15.
*/
// package org.azurespot.cutecollection;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;

import org.azurespot.R;

/**
 * Created by mizu on 2/5/15.
 */
public class GridViewPhotoAdapter extends ArrayAdapter<PhotoGridItem> {

    public Context context;
    private int resourceId;
    Bitmap bm;

    public GridViewPhotoAdapter(Context context, int layoutResourceId) {
        super(context, layoutResourceId);
        this.context = context;
        this.resourceId = layoutResourceId;
    }

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

        View row = convertView;
        final ViewHolder holder;

        if (row == null) {

            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(resourceId, parent, false);

            holder = new ViewHolder();
            holder.imageView = (ImageView) row.findViewById(R.id.photo_grid_view);
            // stores holder with view
            row.setTag(holder);

        } else {

            holder = (ViewHolder)row.getTag();
        }

        PhotoGridItem photoGridItem = getItem(position);

        if (photoGridItem != null) {
            bm = photoGridItem.getImage();
            holder.imageView.setImageBitmap(bm);

            // positioning the image in the GridView slot
            holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            holder.imageView.setLayoutParams(new LinearLayout.LayoutParams(270, 270));
        }

        return row;

    }

    public class ViewHolder{
        ImageView imageView;
    }

}

5 个答案:

答案 0 :(得分:1)

Fragment.onPause()与Fragment的可见性无关。 Fragment.onPause()与它的封装Activity.onPause()绑定在一起。即只有在调用Activity.onPause()之后才会调用Fragment.onPause()。

如果要在片段可见时更新片段,我建议您使用Fragment.setUserVisibleHint()或者使用ViewPager.onPageChangeListener()告诉您何时选择了片段并相应地更新其内容。 / p>

答案 1 :(得分:1)

也许您可以尝试在onCreateView(...)中修改您的代码:

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

    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.photo_tab, container, false);

    // with fragments, make sure you include the rootView when finding id
    gridView = (GridView) v.findViewById(R.id.photo_grid);

    if(adapter == null)
        adapter = new GridViewPhotoAdapter(getActivity(), R.layout.photo_grid_item);

    // Set the Adapter to GridView
    gridView.setAdapter(adapter);

    if(adapter.getCount()>0)
        adapter.clear();

    adapter.addAll(loadSDCard());

    // add the default icons remaining, to GridView, if less than 24 files on SD card
    for (int i = 0; i < (24 - photoList.size()); i++) {

        adapter.add(new PhotoGridItem(BitmapFactory.decodeResource(getResources(),
                R.drawable.ic_photo_placeholder)));
    }

    adapter.notifyDataSetChanged(); //that was missing!!!  

    return v;
}

希望这有帮助!

答案 2 :(得分:0)

在您的片段onCreateView中,尝试检查savedInstanceState是否为空:

 if (savedInstanceState == null) {
     //Add all your images to the adapter
 }

这样,您应该确保在第一次加载片段视图时,只将图像添加到适配器。

答案 3 :(得分:0)

PhotoTab片段的onCreateView会被触发多次,例如当用户切换应用程序(Android可能需要卸载您的应用程序以获取内存)和旋转屏幕时。因此,从您的代码中,我认为它们可能在一段时间内都是重复的。我认为你的设计是这样的,重新加载图像是在onCreateView方法中完成的。一个缺点可能是性能,但现在不要担心。

我的建议是修改loadSDCard()以检查文件是否已被处理或显示。在您的代码示例中:

private ArrayList<PhotoGridItem> loadSDCard() {
    ...
    for (File singleFile : files) {
...
       // Check if this is a new bitmap file
       if (photoList.contains(bitmap) == false) {
          photoList.add(new PhotoGridItem(bitmap));
       }

    }
}

答案 4 :(得分:0)

虽然我找到了解决重复问题的方法,但我得到重复的真正原因是因为我使loadSDCard()方法返回ArrayList<>。我意识到我不需要这样做。因此,当我将方法更改为void时,我可以刷新选项卡并加载SD卡,但每次都会从头开始,并将照片项加载到旧项目上,不会重复。我真的不知道为什么在该方法中返回一个ArrayList<>变量(我正在返回photoList)这样做,但希望如果你将来有重复项,其他人也会得到帮助。