Android Volley error in getInstance(this) when adding ImageLoader

匆匆过客 提交于 2019-12-20 21:01:03

问题


I am following up image cashing tutorial using Volley on Android developers, I am having problem with requesting an image request and caching it, I guess because of the singelton that I created (copied from the tutorial).

My Eclipse is giving error in the getInstance(this) because this is context and I am requesting an image I guess.

ImageRequest request = new ImageRequest(
    url,
    new Response.Listener<Bitmap>() {
        @Override
        public void onResponse(Bitmap bitmap) {
            mNetworkImageView = (NetworkImageView) findViewById(R.id.ImageView);
            mImageLoader = MySingleton.getInstance(this).getImageLoader();
            mNetworkImageView.setImageUrl(IMAGE_URL, mImageLoader);
        //  mImageLoader = MySingleton.getInstance(this).getImageLoader();
        //  mImageLoader.get(IMAGE_URL, ImageLoader.getImageListener(mImageView,
        //      R.drawable.ic_launcher, R.drawable.ic_launcher));
            }
        },
    0,
    0,
    null,
    new Response.ErrorListener() {
        public void onErrorResponse(VolleyError error) {
        //  mImageView.setImageResource(R.drawable.ic_launcher);
        }
    });
MySingleton.getInstance(this).addToRequestQueue(request);

This is singleton:

package com.example.p;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;

import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

public class MySingleton {
    private static MySingleton mInstance;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;
    private static Context mCtx;

    private MySingleton(Context context) {
        mCtx = context;
        mRequestQueue = getRequestQueue();

        mImageLoader = new ImageLoader(
            mRequestQueue,
            new ImageLoader.ImageCache() {
                private final LruCache<String, Bitmap>
                    cache = new LruCache<String, Bitmap>(20);

                @Override
                public Bitmap getBitmap(String url) {
                    return cache.get(url);
                }

                @Override
                public void putBitmap(String url, Bitmap bitmap) {
                    cache.put(url, bitmap);
                }
            });
    }

    public static synchronized MySingleton getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new MySingleton(context);
        }
        return mInstance;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            // getApplicationContext() is key, it keeps you from leaking the
            // Activity or BroadcastReceiver if someone passes one in.
            mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
        }
        return mRequestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req) {
        getRequestQueue().add(req);
    }

    public ImageLoader getImageLoader() {
        return mImageLoader;
    }
}

I am able to get the image and display it in such way , but I need to cache it , so I guess it to add it in a request right ? .. any help ?

mNetworkImageView = (NetworkImageView) findViewById(R.id.ImageView);
mImageLoader = MySingleton.getInstance(this).getImageLoader();
mNetworkImageView.setImageUrl(IMAGE_URL, mImageLoader);

回答1:


This is my working sample code. Hope this help:

MainActivity.java:

import ...

public class MainActivity extends Activity {

    final Context mContext = this;   

    @Override

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        NetworkImageView mNetworkImageView = (NetworkImageView) findViewById(R.id.networkImageView);

        String mUrl = "http://192.168.0.100/api/getimage";
        mNetworkImageView.setImageUrl(mUrl, VolleySingleton.getInstance(mContext).getImageLoader());       
    }

    ...  

}

VolleySingleton.java:

public class VolleySingleton {
    private static VolleySingleton mInstance;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;
    private static Context mContext;

    private VolleySingleton(Context context) {
        mContext = context;
        mRequestQueue = getRequestQueue();

        mImageLoader = new ImageLoader(mRequestQueue,
                new ImageLoader.ImageCache() {
                    private final LruCache<String, Bitmap>
                            cache = new LruCache<>(20);

                    @Override
                    public Bitmap getBitmap(String url) {
                        return cache.get(url);
                    }

                    @Override
                    public void putBitmap(String url, Bitmap bitmap) {
                        cache.put(url, bitmap);
                    }
                });
    }

    public static synchronized VolleySingleton getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new VolleySingleton(context);
        }
        return mInstance;
    }

    private RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            // getApplicationContext() is key, it keeps you from leaking the
            // Activity or BroadcastReceiver if someone passes one in.
            mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext(), 10 * 1024 * 1024); // this for caching
        }
        return mRequestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req) {
        getRequestQueue().add(req);
    }

    public ImageLoader getImageLoader() {
        return mImageLoader;
    }   
}

activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:context=".MainActivity">       

        <com.android.volley.toolbox.NetworkImageView
            android:id="@+id/networkImageView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />       

</LinearLayout>

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.volleyapp" >

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>        
    </application>

</manifest>



回答2:


You´r in the wrong Context .. init a class member

private final Context ctx = this; 

and than use ctx inside onResponse

mImageLoader = MySingleton.getInstance(ctx).getImageLoader();



回答3:


One optimization suggestion for the getInstance method is to use double checked locking as it only synchronizes in case the instance is actually null:

private volatile static VolleySingleton self;

public static VolleySingleton getInstance(Context context) {
    if (self == null) {
        //Using double checked locking
        synchronized (VolleySingleton.class) {
            if (self == null) {
                //Using app context prevents leaking of activity context
                self = new VolleySingleton(context.getApplicationContext());
            }
        }
    }
    return self;
}

More information on singletons and the different ways of instantiating them can be found here.

The volatile keyword ensures, that the field is immediately seen by all threads and is not cached thread-locally. If the getInstance did not require a Context, there are other method explained in the link that would be more suitable than double checked locking.



来源:https://stackoverflow.com/questions/31972334/android-volley-error-in-getinstancethis-when-adding-imageloader

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!