Android 이미지 비동기식 로드

16403 단어
안드로이드 프로그램을 개발하면 일반적으로 두 가지 조작이 있다. 그림의 비동기적 불러오기와 캐시이다. 그림의 비동기적 불러오기는 대부분 인터넷에서 그림을 읽는 것이다(로컬 그림 미리 보기 그림 생성 등 조작). 네트워크 조작을 줄이기 위해 그림의 불러오기 속도를 높이기 위해서는 그림에 대한 캐시가 필요하다.그래서 인터넷의 많은 사진들이 비동기적으로 불러오는 방법은 모두 그림의 캐시와 밀접한 관계를 가진다.그러나 사용자가 이미 캐시와 관련된 라이브러리를 가지고 있기 때문에 사용하기가 좀 번거로울 수도 있다.
최근에 그림과 관련된 문제를 처리할 때 원래 자신이 쓴 그림이 불러오는 것이지만 일부 상태의 제어는 비교적 번거롭다. 예를 들어ListView가 굴러갈 때 ImageView가 다시 사용하기 때문에 게으름을 피우고 기존 자원을 충분히 이용하는 태도로 인터넷에서 그림이 비동기적으로 불러오는 코드를 찾아 결국GreenDroid UI 라이브러리에서 하나를 찾았다.그중에 AsyncImageView의 사용자 정의 View는 비동기적으로 그림을 불러오는 데 사용되지만 인터넷의 대부분의 그림 비동기적으로 불러오는 방법과 마찬가지로 그림의 캐시와 연결되어 있지만 간단한 메모리 캐시일 뿐 파일 캐시가 없다.그림의 불러오는 방법도 다른 것과 같이 쓰기가 막혔기 때문에 사용 범위를 제한합니다. 인풋 스트리밍을 통해decode 그림만 사용할 수 있고, 미리 보기 그림이나 다른 그림 처리를 만드는 비동기적인 처리는 사용할 수 없습니다.기존의 클래스 라이브러리를 수정하는 것은 항상 자기가 처음부터 쓴 것보다 간단하기 때문에 AsyncImageView를 약간 수정하여 캐시와 그림 불러오는 방법을 사용자 정의할 수 있도록 했다. AsyncImageView에 대한 약간의 수정은 대부분이 다른 원본 코드이다.
1. 핵심 클래스
ImageLoader: 이미지 로드 코어 클래스, 내부 스레드 풀로 이미지 로드
ImageRequest: 이미지 로드 요청을 나타냅니다.
AsyncImageView:사용자 정의 이미지 비동기식 로드 View
LoadMethod: 사용자 정의 그림 불러오는 방법의 인터페이스입니다. 이 인터페이스를 통해 그림의 불러오는 방법을 사용자 정의할 수 있습니다
CacheCallback: 캐시 인터페이스
AsyncImageView.OnImageViewLoadListener: 이미지 로드 상태 감지(시작, 실패, 끝)
2.그림 로드 방법
public void run() {

            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

            final Handler h = mHandler;
            Bitmap bitmap = null;
            Throwable throwable = null;

            h.sendMessage(Message.obtain(h, ON_START));

            try {
                if (TextUtils.isEmpty(mUrl)) {
                    throw new Exception("The given URL cannot be null or empty");
                }

                //           ,        
                if (mLoadMethod != null) {
                    bitmap = mLoadMethod.load(mUrl);
                } else {

                    InputStream inputStream = null;

                    // Asset
                    if (mUrl.startsWith("file:///android_asset/")) {
                        inputStream = sAssetManager.open(mUrl.replaceFirst(
                                "file:///android_asset/", ""));
                    }
                    // File
                    else if (mUrl.startsWith("file:///") || mUrl.startsWith("/")) {
                        if (mUrl.startsWith("file:///"))
                            mUrl = mUrl.replaceFirst("file:///", "/");
                        inputStream = new FileInputStream(mUrl);
                    }
                    // NetWork
                    else {
                        //   URL      ,          URL    InputStream         null,   HttpClient
                        HttpGet httpRequest = new HttpGet(mUrl);
                        HttpClient httpclient = new DefaultHttpClient();
                        HttpParams httpParams = new BasicHttpParams();
                        HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
                        HttpConnectionParams.setSoTimeout(httpParams, 5000);
                        httpRequest.setParams(httpParams);
                        HttpResponse response = (HttpResponse)httpclient.execute(httpRequest);
                        HttpEntity entity = response.getEntity();
                        BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
                        InputStream instream = bufHttpEntity.getContent();
                        BufferedInputStream bi = new BufferedInputStream(instream);
                        inputStream = bi;
                    }

                    //   AsyncImageView    BitmapFactory.Options   ,              ,         inSampleSize,
                    //          BitmapFactory.Options,                   LoadMethod  
                    bitmap = BitmapFactory.decodeStream(inputStream, null,
                            (mOptions == null) ? sDefaultOptions : mOptions);
                    inputStream.close();
                }
                if (mBitmapProcessor != null && bitmap != null) {
                    final Bitmap processedBitmap = mBitmapProcessor.processImage(bitmap);
                    if (processedBitmap != null) {
                        bitmap.recycle();
                        bitmap = processedBitmap;
                    }
                }

            } catch (Exception e) {
                Log.e(LOG_TAG, "Error while fetching image", e);
                throwable = e;
            }

            if (bitmap == null) {
                if (throwable == null) {
                    throwable = new Exception("Skia image decoding failed");
                }
                h.sendMessage(Message.obtain(h, ON_FAIL, throwable));
            } else {
                h.sendMessage(Message.obtain(h, ON_END, bitmap));
                if (mCache != null) {
                    mCache.writeCache(TextUtils.isEmpty(mCacheKey) ? mUrl : mCacheKey, bitmap);
                }
            }
        }

LoadMethod를 사용자 정의하면 해당 방법으로 그림을 불러옵니다. 사용자 정의가 없으면 기본 불러오는 방법을 사용합니다. 로컬 그림, Asset 그림과 네트워크 그림, GreenDroid의 원본 코드에서 네트워크 그림을 불러오는 URL을 사용합니다. 그러나 저희가 이전에 네트워크 그림을 불러올 때 문제가 발생했습니다.어떤 기종은 URL 클래스를 통해 얻은 ImputStream 해석 그림이 항상 null로 되돌아오기 때문에 HttpClient로 변경됩니다.
3.사용법
AsyncImageView의 setPath 방법을 사용하여 이미지를 로드하면 setPath에는 다음과 같은 3가지 재로드 방법이 있습니다.
public void setPath(String path)
public void setPath(String path, LoadMethod loadMethod)
public void setPath(String path, LoadMethod loadMethod, String cacheKey)
첫 번째 파라미터는 불러올 그림의 경로를 지정하고, 두 번째 파라미터는 사용자 정의 그림 불러오는 방법을 지정하며, 지정하지 않으면 기본값을 사용합니다.
세 번째 파라미터를 추가하는 것은 캐시용이다. 일반적으로 불러올 그림의 경로가 유일하기 때문에 보통 첫 번째 파라미터를 캐시 키로 하면 된다. 그러나 특수한 경우도 있다. 예를 들어 랜에 있는 그림을 읽으면 IP를 자동으로 얻는다. 그림 경로에 따라 캐시 키로 하는 것은 적합하지 않을 수도 있다.따라서 필요에 따라 캐시로 사용할 키를 수동으로 지정해야 합니다.
/**
     *            ,       , Asset    (file:///android_asset),       (file:/// /)
     * 
     * @param path          ,   null       
     * @param loadMethod            ,   null,          
     * @param cacheKey   key
     */
    public void setPath(String path, LoadMethod loadMethod, String cacheKey) {

        // Check the url has changed
        if (mBitmap != null && path != null && path.equals(mUrl)) { // TODO mBitmap != null necessary?
            return;
        }

        stopLoading();
        mUrl = path;
        mCacheKey = cacheKey;
        mLoadMethod = loadMethod;

        // Setting the url to an empty string force the displayed image to the
        // default image
        if (TextUtils.isEmpty(mUrl)) {
            mBitmap = null;
            setDefaultImage();
        } else {
            if (!mPaused) {
                reload();
            } else {
                // We're paused: let's look in a synchronous and efficient cache
                // prior using the default image.
                mBitmap = readCache(); // TODO       
                if (mBitmap != null) {
                    setImageBitmap(mBitmap);
                } else {
                    setDefaultImage();
                }
            }
        }
    }
public void reload(boolean force) {
        if (mRequest == null && mUrl != null) {

            // Prior downloading the image ... let's look in a cache !
            mBitmap = null;
            if (!force) {
                // This may take a long time.
                mBitmap = readCache();
            }

            if (mBitmap != null) {
                setImageBitmap(mBitmap);
                return;
            }

            setDefaultImage();
            mRequest = new ImageRequest(mUrl, this, mImageProcessor, mOptions, mCacheKey);
            mRequest.load(getContext(), mLoadMethod);
            if (ImageLoader.getInstance() != null && ImageLoader.getInstance().getCache() == null) {
                ImageLoader.getInstance().setCache(mCache);
            }
        }

readCache()는 다음과 같은 읽기 캐시에 사용됩니다.
    private Bitmap readCache() {
        if (mCache != null)
            return mCache.readCache(TextUtils.isEmpty(mCacheKey) ? mUrl : mCacheKey);
        return null;
    }

이 중 mCache는 사용자가 setCacheCallback (CacheCallback callback) 을 통과할 수 있는 사용자 정의 캐시 방법을 설정하여 그림의 캐시와 캐시를 분리하여 사용자가 기존의 캐시를 사용할 수 있도록 합니다.사용자가 캐시 키를 지정하려면 사용자가 지정한 키를 사용하고, 그렇지 않으면 그림의 경로로 키를 만듭니다.
4.AsyncImageView의 기타 중요한 방법
reload([boolean force]):다시 로드
stopLoading (): 불러오는 것을 중지합니다. 현재 불러오는 중이면 효과가 없고, 불러오는 작업이 불러오는 스레드 탱크 대기열에서 취소됩니다.
setDefaultImage...() 클래스 방법: 기본 그림을 설정합니다.
setPause (boolean pause): 그림을 로드할지 여부
 
소스 다운로드: AsyncImage

좋은 웹페이지 즐겨찾기