322013字节分配的内存不足

时间:2016-01-21 02:14:37

标签: android memory bitmap

我想在交错网格布局中显示我从Flickr获得的位图。照片在开始时显示良好。但是,当我进一步向下滚动图像时,它会返回"错误 - 内存不足"。显示位图图像时如何避免内存不足错误?以下是我的日志:

    E/dalvikvm-heap: Out of memory on a 322013-byte allocation.
01-21 09:56:42.718 25341-25360/com.example.myapp I/dalvikvm: "Thread-557" prio=5 tid=13 RUNNABLE
01-21 09:56:42.718 25341-25360/com.example.myapp I/dalvikvm:   | group="main" sCount=0 dsCount=0 obj=0x4251a118 self=0x5f496370
01-21 09:56:42.718 25341-25360/com.example.myapp I/dalvikvm:   | sysTid=25360 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1598646248
01-21 09:56:42.718 25341-25360/com.example.myapp I/dalvikvm:   | state=R schedstat=( 24035935571 12370314782 38194 ) utm=2070 stm=333 core=1
01-21 09:56:42.718 25341-25360/com.example.myapp I/dalvikvm:     at java.io.ByteArrayOutputStream.toByteArray(ByteArrayOutputStream.java:~122)
01-21 09:56:42.718 25341-25360/com.example.myapp I/dalvikvm:     at com.android.volley.toolbox.BasicNetwork.entityToBytes(BasicNetwork.java:222)
01-21 09:56:42.718 25341-25360/com.example.myapp I/dalvikvm:     at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:105)
01-21 09:56:42.718 25341-25360/com.example.myapp I/dalvikvm:     at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:105)
01-21 09:56:42.718 25341-25360/com.example.myapp W/dalvikvm: threadid=13: thread exiting with uncaught exception (group=0x4174cd58)
01-21 09:56:42.718 25341-25360/com.example.myapp I/Process: Sending signal. PID: 25341 SIG: 9
01-21 09:56:42.838 1057-1399/? I/ActivityManager: Process com.example.myapp (pid 25341) has died.
01-21 09:56:42.878 1057-1068/? W/InputMethodManagerService: Got RemoteException sending setActive(false) notification to pid 25341 uid 10186
01-21 09:56:42.878 1315-1326/? W/Binder: Caught a RuntimeException from the binder stub implementation.
                                         java.lang.NullPointerException
                                             at android.inputmethodservice.IInputMethodWrapper.setSessionEnabled(IInputMethodWrapper.java:280)
                                             at com.android.internal.view.IInputMethod$Stub.onTransact(IInputMethod.java:129)
                                             at android.os.Binder.execTransact(Binder.java:404)
                                             at dalvik.system.NativeStart.run(Native Method)

以下是从Flickr获取图像的程序

@SuppressLint("ValidFragment")
public class FragmentRecent extends Fragment implements FragmentManager.OnBackStackChangedListener{
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    private StaggeredGridView mStaggeredView;
    private RequestQueue mVolleyQueue;
    private ProgressDialog mProgress;
    private int currPage=1;
    GsonRequest<FlickrResponsePhotos> gsonObjRequest;

    private RelativeLayout mListFooter;
    private boolean isLoading = false;

    private final String TAG_REQUEST = "MY_TAG";

    private StaggeredGridView.OnScrollListener scrollListener = new StaggeredGridView.OnScrollListener() {
        public void onTop() {
        }

        public void onScroll() {
            loadMoreData();//edit from onBottom
        }

        public void onBottom() {
           // loadMoreData(); TBS commented out for loading new data while scrolling
        }
    };

    private void loadMoreData() {

        if ( isLoading )
            return;

        mListFooter.setVisibility(View.VISIBLE);
        isLoading = true;
        flickerGetImagesRequest();
    }

    private void flickerGetImagesRequest() {
        {

            String url = "https://api.flickr.com/services/rest";
            Uri.Builder builder = Uri.parse(url).buildUpon();
            builder.appendQueryParameter("api_key", "5e045abd4baba4bbcd866e1864ca9d7b");
            //builder.appendQueryParameter("method", "flickr.interestingness.getList"); //TBS
            builder.appendQueryParameter("method", "flickr.photos.search");
            builder.appendQueryParameter("tags",mMenuChoice);
            //builder.appendQueryParameter("sort","relevance");
            builder.appendQueryParameter("format", "json");
            builder.appendQueryParameter("nojsoncallback", "1");
         //   builder.appendQueryParameter("per_page", "10");
            builder.appendQueryParameter("page", Integer.toString(currPage));

            gsonObjRequest = new GsonRequest<FlickrResponsePhotos>(Request.Method.GET, builder.toString(),
                    FlickrResponsePhotos.class, null, new Response.Listener<FlickrResponsePhotos>() {
                @Override
                public void onResponse(FlickrResponsePhotos response) {
                    try {
                        if(response != null) {
                            parseFlickrImageResponse(response);
                            currPage++;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        showToast("JSON parse error");
                    }
                    stopProgress();
                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {
                    // Handle your error types accordingly.For Timeout & No connection error, you can show 'retry' button.
                    // For AuthFailure, you can re login with user credentials.
                    // For ClientError, 400 & 401, Errors happening on client side when sending api request.
                    // In this case you can check how client is forming the api and debug accordingly.
                    // For ServerError 5xx, you can do retry or handle accordingly.
                    if( error instanceof NetworkError) {
                    } else if( error instanceof ClientError) {
                    } else if( error instanceof ServerError) {
                    } else if( error instanceof AuthFailureError) {
                    } else if( error instanceof ParseError) {
                    } else if( error instanceof NoConnectionError) {
                    } else if( error instanceof TimeoutError) {
                    }
                    //mStaggeredView.onRefreshComplete();
                    stopProgress();
                    showToast(error.getMessage());
                }
            });
            gsonObjRequest.setTag(TAG_REQUEST);
            mVolleyQueue.add(gsonObjRequest);
        }
    }

    private void parseFlickrImageResponse(FlickrResponsePhotos response) {
        FlickrGetImagesResponse photos = response.getPhotos(); //pass array of images to Picture Activity
        String[] photoUrl;
        photoUrl = new String[photos.getPhotos().size()];
        for (int index = 0; index < photos.getPhotos().size(); index++) {

            FlickrImage flkrImage = photos.getPhotos().get(index);
            photoUrl[index]=flkrImage.getImageUrl();
            StaggeredGridViewItem item = null;
            item = new GridItem(getActivity(), flkrImage,photoUrl); //pass one image of index
            mStaggeredView.addItem(item);

        }

    }

    private void showToast(String msg) {
        Toast.makeText(getActivity(), msg, Toast.LENGTH_LONG).show();
    }

    private void stopProgress() {
        isLoading = false;
        mListFooter.setVisibility(View.GONE);
        mProgress.cancel();
    }

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    private OnFragmentInteractionListener mListener;

    private String mMenuChoice;

    public FragmentRecent(String menuChoice) {
        // Required empty public constructor
        mMenuChoice=menuChoice;

    }

    //private GridViewAdapter adapter;
    private GridView gridView;
    private int columnWidth;
    private Integer[] photosList;

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment FragmentOne.
     */



    // TODO: Rename and change types and number of parameters
    public static FragmentRecent newInstance(int page) {
        FragmentRecent fragment = new FragmentRecent("recentValue");
        Bundle args = new Bundle();
        args.putInt("someInt", page);
        fragment.setArguments(args);
        return fragment;
    }

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

        if(mVolleyQueue==null){
            mVolleyQueue= Volley.newRequestQueue(getActivity());
        }
        mVolleyQueue = StaggeredDemoApplication.getRequestQueue(getActivity());//added this
        showProgress();
        //added async task
        //new PrefetchData().execute();

        flickerGetImagesRequest();
    }

    private void showProgress() {
        mProgress = ProgressDialog.show(getActivity(), "", "Loading...");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_flickrstart, container, false);
//        gridView = (GridView) rootView.findViewById(R.id.grid_view);
//        gridView.setVisibility(View.VISIBLE);
//        gridView.setAdapter(new GridViewAdapter(getActivity()));
        mListFooter = (RelativeLayout) rootView.findViewById(R.id.footer);

        mStaggeredView = (StaggeredGridView) rootView.findViewById(R.id.staggeredview);
        // Be sure before calling initialize that you haven't initialised from XML
        //mStaggeredView.initialize(2, StaggeredGridView.Mode.FIXED);
        mStaggeredView.setOnScrollListener(scrollListener);

        Toast.makeText(getActivity(),mMenuChoice,Toast.LENGTH_SHORT).show();
        return rootView;

    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    @Override
    public void onBackStackChanged() {

    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p/>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }

}

以下是将图像添加到gridItem

的代码
public class GridItem extends StaggeredGridViewItem {

    private Context mContext;
    private ImageLoader mImageLoader;
    private FlickrImage mImage;
    private View mView;
    private int mHeight;
    private String[] mPhotoUrl;


    public GridItem(Context context, FlickrImage image, String[] photoUrl) {
        mImage = image;
        mContext = context;
        mImageLoader = StaggeredDemoApplication.getImageLoader();
        mPhotoUrl=photoUrl;
    }


    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    @Override
    public View getView(int position, LayoutInflater inflater, ViewGroup parent) {
        // TODO Auto-generated method stub
        mView = inflater.inflate(R.layout.grid_item, null);
        final ImageView image = (ImageView) mView.findViewById(R.id.image);

        mImageLoader.get(mImage.getImageUrl(),
                ImageLoader.getImageListener(image, R.drawable.bg_no_image, android.R.drawable.ic_dialog_alert), parent.getWidth(), 0);
        image.setOnClickListener(new OnImageClickListener(position));//correct position 11,12,13..
        return mView;
    }

    @Override
    public int getViewHeight(LayoutInflater inflater, ViewGroup parent) {
        FrameLayout item_containerFrameLayout = (FrameLayout)mView.findViewById(R.id.container);
        item_containerFrameLayout.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        mHeight = item_containerFrameLayout.getMeasuredHeight();
        return mHeight;
    }

    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    private class OnImageClickListener implements View.OnClickListener {
        int _position;

        public OnImageClickListener(int position) {
            this._position = position;
        }


        @Override
        public void onClick(View v) {
            Intent iSlider = new Intent(mContext, FullScreenImageActivity.class);
            iSlider.putExtra("position", _position); //0
            iSlider.putExtra("array",mPhotoUrl);//check whether is old or new array
            iSlider.putExtra("url",mImage.getImageUrl());
            mContext.startActivity(iSlider);
        }
    }
}

以下是图片加载的代码

    public class StaggeredDemoApplication extends Application {

    private static Context applicationContext;
    private static RequestQueue mRequestQueue;
    private static ImageLoader mImageLoader;
    private static BitmapLruCache mBitmapCache;

    public static boolean INIT_FLAG = true;

    public void onCreate() {
        super.onCreate();

        applicationContext = this.getApplicationContext();

        mRequestQueue = Volley.newRequestQueue(applicationContext);
        long size = Runtime.getRuntime().maxMemory()/4;
        mBitmapCache = new BitmapLruCache(30);//(int)size);
        mImageLoader = new ImageLoader(mRequestQueue, mBitmapCache);
    }

    public static RequestQueue getRequestQueue(Context mContext) {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(mContext);
        }
        return mRequestQueue;
    }

    public static ImageLoader getImageLoader() {
        if (mImageLoader != null) {
            return mImageLoader;
        } else {
            throw new IllegalStateException("ImageLoader not initialized");
        }
    }

}

0 个答案:

没有答案