다 뒤져 보았는데 정말 이보다 좋은 튜토리얼은 존재하지 않았다....



소스코드 또한 다운로드 가능하다...

오류 : java.net.SocketException: The operation timed out

오류 소스
	// Send data
	url = new URL("http://{your ip}:{your port}/{context}/{uri}");
	conn = url.openConnection();
	conn.setDoOutput(true);
	conn.setConnectTimeout(0);
	wr = new OutputStreamWriter(conn.getOutputStream());
	wr.write("date=2011-01-02");	// test code
	wr.flush();

원인 
  - 3G를 이용한 socket 통신 실패

맞춤검색


상세 
  - 서버와의 연결 시 연결이 되지 않고 오류가 남..
    
해결
   - 서버를 켤 것..
  - 서버가 켜져 있다면 방화벽을 확인 할 것.


위 그림 처럼 assets하위에 폴더를 두고 접근을 하고 싶다면 아래와 같이 하면 된다. 


        AssetManager am = getResources().getAssets();
        InputStream is = am.open("jan/"+(filename));


어제에 이어서 계속.....

먼저 이미지 캐싱을 하기전에 캐싱을 안하게되면 어떤 문제점이 발생되는지부터 알아야하기에 일반적인 GridView를 만들겠습니다.

새로운 프로젝트를 만듭니다.
(가급적이면 비슷하게 하면 더 쉽겠죠...)

API 8로 만드세요.. 잘 못 눌렀어요

프로젝트 생성후 AndroidManifest.xml을 아래와 같이 수정합니다.


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.yeory.gv"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" 
    			 android:label="@string/app_name"
    			 android:debuggable="true">
    			 
        <activity android:name=".ImageList"
                  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>
    
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-sdk android:minSdkVersion="8" />
</manifest> 
android:debuggable="true" -> Eclipse에서 디버그 모드를 가능하게 하는 명령줄입니다.android.permission.INTERNET -> App에서 Internet 접근을 허용하게 하는 권한 입니다.

대충 GridView의 초기 설정은 끝이 났습니다. 
Internet 권한을 준 이유는 당연한 것이겠지만 웹에서 이미지를 가져올 것이기에 그런 것이죠 - 
권한이 없다면 Permission Denied~~~ 에러 납니다.

res 폴더 내에 xml을 저장할 폴더를 만들고 파일을 만들겠습니다.
res 폴더는 App에서 사용할 자원(Resources)을 저장한다고 보시면 됩니다.


그리고 생성된 xml 폴더에 파일을 만듭니다. [ url.xml ] 
이 XML에는 웹에서 불러올 이미지 주소를 적어 줍니다.  

형식은 아래와 같습니다.

<images>
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image01.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image01.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image02.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image02.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image03.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image03.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image04.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image04.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image05.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image05.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image06.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image06.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image07.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image07.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image08.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image08.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image09.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image09.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image10.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image10.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image11.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image11.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image12.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image12.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image13.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image13.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image14.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image14.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image15.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image15.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image16.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image16.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image17.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image17.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image18.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image18.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image19.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image19.jpg" />
		   
	<image description="" uri="http://yeory.just4fun.co.kr/android/image/image20.jpg"
		   thumb="http://yeory.just4fun.co.kr/android/image/thumb/th_image20.jpg" />
</images>
20개 정도만 하겠습니다. 나중에 더 추가해야합니다.

이제 실제 GridView를 layout에 정의하겠습니다.

[ file : res/layout/main.xml]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
	<GridView xmlns:android="http://schemas.android.com/apk/res/android" 
		android:id="@+id/gridView"
		android:layout_width="fill_parent"
		android:layout_height="400dp"
		android:numColumns="auto_fit"
		android:verticalSpacing="10dp"
		android:horizontalSpacing="10dp"
		android:columnWidth="90dp"
		android:fastScrollEnabled="true"
		android:smoothScrollbar="true"
		android:scrollingCache="true"
		android:stretchMode="columnWidth"
		android:gravity="center"
	/>
	<!-- 스크롤에 관련된 정보 보여줄 TextView -->
	<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
		android:id="@+id/logText"
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
	/>
</LinearLayout>

속성들은 대충 보셔도 알거라 생각하기에 그냥 넘깁니다. 
궁금한건 API 보시고 그래도 모르겠으면 구글링 하시고 그게 귀찮으면 댓글로...... ;;

이제 Activity에서 정의한 Layout을 불러와야 합니다.

[ file : ImageList.java ]
package com.yeory.gv;

import android.app.Activity;
import android.os.Bundle;
import android.widget.GridView;

/**
 * =============================================================================
/            프로젝트명 :   GridView_Example
/            화  일  명 :   ImageList.java
/            기      능 :   
/            인      수 :   
/            특이  사항 :
/-----------------------------------------------------------------------------
/                               변경 사항				                     
/-----------------------------------------------------------------------------
/    변경일자       	변경자(작성자)                 		변경 내역                 
/   ----------     	--------------------------       -------------------------
/   2010. 11. 10.       jYeory<jyeory@gmail.com>         	최 초 작 성                      
/==============================================================================
 */
public class ImageList extends Activity {    
	/** Called when the activity is first created. */    

	@Override    
	public void onCreate(Bundle savedInstanceState) {        
		super.onCreate(savedInstanceState);        
		setContentView(R.layout.main);                
		GridView gridView = (GridView) findViewById(R.id.gridView);    
	}
}
여기까지 한 것을 실행시켜 보도록 하죠..

먼저 왼쪽의 +를 눌러서 새로운 실행 환경을 설정해 주어야 합니다. 
눌러서 그림과 같이 적고 선택해 줍니다.

구글 가이드 라인은 휴대폰을 연결하여 작업하는 것을 권장합니다. 그러므로 Automatic이 아닌 Manual로 실행합시다.

실행 되겠죠?

XML을 읽어와 각 정보를 bean에 담아야 합니다.
그러므로 class를 하나 만들겠습니다.
<패키지 명 확인하세요>

[ file : Image.java ]
package com.yeory.gv.model;

/**
 * =============================================================================
/            프로젝트명 :   GridView_Example
/            화  일  명 :   Image.java
/            기      능 :   
/            인      수 :   
/            특이  사항 :
/-----------------------------------------------------------------------------
/                               변경 사항				                     
/-----------------------------------------------------------------------------
/    변경일자       	변경자(작성자)                 		변경 내역                 
/   ----------     	--------------------------       -------------------------
/   2010. 11. 10.      jYeory<jyeory@gmail.com>         		최 초 작 성                      
/==============================================================================
 */
public class Image {
	private String description;
	private String thumbNail;
	private String uri;
	
	public Image() {}
	
	public Image(String d, String u, String t) {
		this.description = d;
		this.uri = u;
		this.thumbNail = t;
	}
	
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public String getUri() {
		return uri;
	}
	public void setUri(String uri) {
		this.uri = uri;
	}

	public void setThumbNail(String thumbNail) {
		this.thumbNail = thumbNail;
	}

	public String getThumbNail() {
		return thumbNail;
	}
}



이젠 xml로 정의한 내용(url)을 가져오도록 하겠습니다.
Activity가 실행되면 가장 먼저 해야할 작업입니다. 그리고 이를 가공하여 다음에 만들 Adapter에 넘겨줘야 하죠.

[ method : init() ]
	private ArrayList wholeImageList = new ArrayList();	// 전체 이미지 담을 것.
	private ArrayList imageList = new ArrayList();	// 부분 이미지 담을 것.
	private XmlPullParser xpp;
	final int size = 15;			// 한번에 보여줄 이미지 개수
	private int totalSize = 0;		// paging에 필요
	private int currentPage = 0;	// paging에 필요
	private int start = 0;			
	private int end = 0;
	
        /**
	 * XML을 읽어들여 전체 이미지를 ArrayList에 넣는다.
	 * 처음으로 호출 되기에 15개만 다른 list에 담아 캐싱. 
	 * @param page
	 * @param size
	 */
	private void init(final int page, final int size) {
		xpp = getResources().getXml(R.xml.url);
		try{
			while ( xpp.getEventType() != XmlPullParser.END_DOCUMENT ){  // 마지막 문서까지
				if ( xpp.getEventType() == XmlPullParser.START_TAG ){
					if ( xpp.getName().equals("image") ){
						wholeImageList.add(new Image(xpp.getAttributeValue(0), xpp.getAttributeValue(1), xpp.getAttributeValue(2)));
					}
				}
				xpp.next();
			}
			
			totalSize = wholeImageList.size();
			currentPage = page;

			start = (page - 1) * size; 
			end = (page*size);
			imageList.addAll(wholeImageList.subList(start, end));
			
		}catch(XmlPullParserException xppe){
			Log.i("error", "init()"+xppe);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
XML을 읽어 <image></image>의 내용을 wholeImageList에 add 합니다.
10개든 100개든 url만 저장하는거죠.
그리고 정해진 개수에 맞게 페이징 처리를 해서 실제 불러올 url만 따로 imageList에 저장하는 것이죠.
Adapter에 넘겨줄 list는 ImageList입니다.

이젠 Grid를 구성할 수 있게 ImageAdapter를 만들겠습니다.

GridView에서 작은 박스들로 그리드를 구성하여 리스팅하게 되는데 이때 사용하는 방법은 Adapter 방식을 사용합니다.
가이드 라인에서도 이미지 처리는 가능하다면 Adapter를 사용하라고 되어 있습니다. 
(참고로 지금 만들 ImageAdapter는 PHP의 Iterator class와 비슷합니다.)

패키지 명이 다릅니다. 확인하세요.


[ file : ImageAdapter.java ]
package com.yeory.gv.util;

import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
/**
 * =============================================================================
/            프로젝트명 :   GridView_Example
/            화  일  명 :   ImageAdapter.java
/            기      능 :   
/            인      수 :   
/            특이  사항 :
/-----------------------------------------------------------------------------
/                               변경 사항				                     
/-----------------------------------------------------------------------------
/    변경일자       	변경자(작성자)                 		변경 내역                 
/   ----------     	--------------------------       -------------------------
/   2010. 11. 10.      jYeory<jyeory@gmail.com>         		최 초 작 성                      
/==============================================================================
 */
public class ImageAdapter extends BaseAdapter{
	private final String LOG_TAG = "ImageAdapter";
	
	@Override
	public int getCount() {
		Log.i(LOG_TAG, "called getCount()");
		return 0;
	}

	@Override
	public Object getItem(int position) {
		Log.i(LOG_TAG, "called getItem()");
		return null;
	}

	@Override
	public long getItemId(int position) {
		Log.i(LOG_TAG, "called getItemId()");
		return 0;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		Log.i(LOG_TAG, "called getView()");
		return null;
	}

}
기본적인 ImageAdapter의 구조입니다. @Override 메서드는 모두 구현되어야만 합니다.
각 Log는 각 메서드의 호출 순서를 확인하기 위해서입니다만 본인은 다 까먹었습니다.. ㅋ

구글 데모에서는 Activity 내에 클래스를 만들어 사용을 했는데 전 그 방법을 좋아하지 않습니다.
가능하다면 위와 같이 외부 클래스로 작성 할것을 미리 알려드립니다.


기본적인 뼈를 만들었으니 살을 붙여야합니다.

[ file : ImageAdapter.java ]

package com.yeory.gv.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;

import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;

import com.yeory.gv.model.Image;
/**
 * =============================================================================
/            프로젝트명 :   GridView_Example
/            화  일  명 :   ImageAdapter.java
/            기      능 :   
/            인      수 :   
/            특이  사항 :
/-----------------------------------------------------------------------------
/                               변경 사항				                     
/-----------------------------------------------------------------------------
/    변경일자       	변경자(작성자)                 		변경 내역                 
/   ----------     	--------------------------       -------------------------
/   2010. 11. 10.      jYeory<jyeory@gmail.com>        		최 초 작 성                      
/==============================================================================
 */
public class ImageAdapter extends BaseAdapter{
	private final String LOG_TAG = "ImageAdapter";
	private Context mContext;
    private ImageView imageView;
    private ArrayList lists;
    private BitmapDrawable bd;
    
    public ImageAdapter(Context c) {
        mContext = c;
    }
    
    public ImageAdapter(Context c, ArrayList lists){
    	mContext = c;
    	this.lists = lists;
    }
	
	
	@Override
	public int getCount() {
		Log.i(LOG_TAG, "called getCount()");
		return lists.size();
	}

	@Override
	public Object getItem(int position) {
		Log.i(LOG_TAG, "called getItem()");
		return null;
	}

	@Override
	public long getItemId(int position) {
		Log.i(LOG_TAG, "called getItemId()");
		return 0;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		Log.i(LOG_TAG, "called getView()");
		if (convertView == null) {  // if it's not recycled, initialize some attributes.
    		imageView = new ImageView(mContext);
    		imageView.setLayoutParams(new GridView.LayoutParams(150, 150));
    		imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    		imageView.setPadding(4, 4, 4, 4);
    		
    		bd = downloadBitmap(lists.get(position).getThumbNail());
    		
            imageView.setImageBitmap(bd.getBitmap());
        } else {
            imageView = (ImageView) convertView;
        }
		
		return imageView;
	}
	
	private HttpClient client = new DefaultHttpClient();
	private HttpGet httpRequest = null; 
	private int statusCode;
	private HttpResponse response = null; 
	private BufferedHttpEntity bufHttpEntity = null; 
    private InputStream is = null;
	
	private BitmapDrawable downloadBitmap(String url) {
		Log.i("test", "url : "+url);
        // AndroidHttpClient is not allowed to be used from the main thread
        try {
        	httpRequest = new HttpGet(url); 
            response = client.execute(httpRequest);
            statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) { 
                Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url); 
                return null;
            }
            
            bufHttpEntity = new BufferedHttpEntity(response.getEntity()); 
            if (bufHttpEntity != null) {
                try {
                	is = bufHttpEntity.getContent();
                    // return BitmapFactory.decodeStream(inputStream);
                    // Bug on slow connections, fixed in future release.
                    return new BitmapDrawable(BitmapFactory.decodeStream(is));
                } finally {
                    if (is != null) {
                    	is.close();
                    }
                    bufHttpEntity.consumeContent();
                }
            }
        } catch (IOException e) {
        	httpRequest.abort();
            Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e);
        } catch (IllegalStateException e) {
        	httpRequest.abort();
            Log.w(LOG_TAG, "Incorrect URL: " + url);
        } catch (Exception e) {
        	httpRequest.abort();
            Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e);
        }
        return null;
    }
}
ImageAdapter의 생성자를 통해 context와 url이 담겨져 있는 list를 받게 되어 있습니다.
이후 getView가 호출되면 순서에 해당하는 list의 url을 찾아 통신을 하게 되어 있죠.
이부분은 캐싱을 할 때 자세히 다루겠습니다...

글이 점점 길어집니다.. 하...

이렇게 만든 ImageAdpater를 Activity에 등록해주어야 합니다.

[ method : onCreate() ]

	private GridView gridView;
	private TextView textView;
	private ImageAdapter adapter; 
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        init(1, size);
        
        textView = (TextView) findViewById(R.id.logText);
        gridView = (GridView) findViewById(R.id.gridView);
        adapter = new ImageAdapter(this, imageList);
        
        gridView.setAdapter(adapter);
    }

이제 실행하여야하는데 와이파이를 이용하길 권장합니다.
실행시 그리드로 구성되고 스크롤도 가능합니다.

하지만 문제가 발생합니다.

1. 스크롤 시 보여지는 thumbNail이 변경됩니다.
GrdiView의 문제점이라고 할 수 있는데 ImageView가 Activity 밖으로 벗어나게 되면 해당 ImageView는 소멸(이라 쓰고 잠수라고 읽습니다..) 됩니다. (screen out)
그리고 다시 Activity안으로 ImageView가 다시 보여지게 된다면 재사용(recycled)이 가능해져 기존 사용한 ImageView를 불러오는데 이때 이미지가 변경된다고 짐작하고 있습니다...
(다 변경되는건 아니고 Activity 밖으로 스크롤된 이미지만!!)
2. 스크롤 시 다음 페이지를 가지고 와야한다.


여기까지 입니다.

풀 소스를 첨부합니다.

아... 힘들다.. 



 2011. 11. 02일 수정

이전에 적었던 1번 문제가 해결되었습니다.
아마 API가 업데이트 되면서 해결된거 같은데 기록을 뒤지자니 끝도 없어 포기;

현재 위 예제는 HTC 넥서스 원, HTC 레이더 LTE 기종에서 실행되는걸 확인 했습니다. 


  1. 이현태 2011.01.20 09:58 신고

    아..좋은내용 감사합니다!^^

    한참을 찾아헤매다 님의 블로그에서 찾게 되었네요.

    아직 실력이 부족해서..매일 구글링으로 자료를 찾아 다니고만 있네요.

    그래도 즐거운 마음으로 안드로이드 공부중입니다^^ 자료 감사합니다~

    캐싱부분도 기대하고 있겠습니다^^

  2. yap 2011.10.26 14:56 신고

    위에 써주신 문제점을 확인해보고 싶은데...
    다운로드 받아서 import한거 실행시켜보니까 프로그램이 죽어버리네요ㅜ.ㅜ
    와이파이도 연결 잘 돼있는데... 왜 그런지 아시나요?ㅎㅎ

- 편의상 편하게 쓸랍니다 -

안드로이드에서 제공하는 모든 이미지 관련 API는 기기내의 MediaStorage를 기반으로 한다. 

ThumbNail을 생성해주는 Images.Thumbnails.getThumbnail 메서드 또한 기기내의 파일을 위한 것이다.

구글에서 제공하는 Demo에서 사용되는 것 역시 기기(이하 로컬)내의 파일이다.

Activity에 GridView를 불러들이고 gridView에 ImageAdapter를 사용하여 그리드를 구현한다는 것인데 - 
(Adapater 사용은 구글에서 권고하는 가이드 라인에 포함되어 있는 코딩 방법이다)

Demo에 나와있는 아주 표준적인 ImageAdapter를 먼저 살펴보자...


public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    public ImageAdapter(Context c) {
        mContext = c;
    }

    public int getCount() {
        return mThumbIds.length;
    }

    public Object getItem(int position) {
        return null;
    }

    public long getItemId(int position) {
        return 0;
    }

    // create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {  // if it's not recycled, initialize some attributes
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(8, 8, 8, 8);
        } else {
            imageView = (ImageView) convertView;
        }

        imageView.setImageResource(mThumbIds[position]);
        return imageView;
    }

    // references to our images
    private Integer[] mThumbIds = {
            R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_4, R.drawable.sample_5,
            R.drawable.sample_6, R.drawable.sample_7,
            R.drawable.sample_0, R.drawable.sample_1,
            R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_4, R.drawable.sample_5,
            R.drawable.sample_6, R.drawable.sample_7,
            R.drawable.sample_0, R.drawable.sample_1,
            R.drawable.sample_2, R.drawable.sample_3,
            R.drawable.sample_4, R.drawable.sample_5,
            R.drawable.sample_6, R.drawable.sample_7
    };
}

간단한 구조로 되어있다. 또한 이미지를 res/drawable 폴더에 다 넣어서 직접 가져다 쓰고 있다.
이건 로컬의 이미지를 구현하기 위한 방법이므로 아주 적당하다고 할 수 있다. 
(하지만 100장이 넘는 이미지라면..? ID 다 적어줄 건가..? 당신은 어찌할 것인가??)

우선 그리드를 구성하는 하나의 이미지는 ImageView로 구성이 된다.
그리고 이 ImageView는 getView()에서 생성이 되는데 ImageView의 핵심인 이미지 파일의 정보 또한 getView()에서 처리되고 있다.

ImageAdapter를 사용하는 방법은 다음과 같다.

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    GridView gridview = (GridView) findViewById(R.id.gridview);
    gridview.setAdapter(new ImageAdapter(this));
}



기본적인 Demo에 관련된 자세한 사항은 이 글보다는 아래 글을 참고하길 바란다.


로컬의 이미지들을 처리할 것이라면 정말 이보다 좋은 방법은 있을 수 없다.
또한 이미 생성된 ImageView는 재사용(recycled)이 가능하기 때문에 자원(resource) 관리에도 도움이 된다.

로컬에서의 이미지 처리시 생각해야할 부분은 이미지 정보들을 어떻게 가져올 것인가에 대한 것이다.

가장 극단적인 예로 SD 카드의 이미지를 처리할려고 하면 정말 코드 몇줄이면 끝나지만 - 
자신이 만들고 있는 어플에서 쓸 이미지를 부를거라면? 
근데 그 이미지들이 1~2장이 아니라 100장이 된다면?  언제 R.id.xx 해서 100개 다 찍고 있을건가.?

즉 GridView를 이용하여 웹(또는 로컬)에서 이미지를 가져와 작업을 하려면 위 사항을 최소한으로 생각해보아야 한다.





계속 쭉쭉 이어 적을려고 했으나 퇴근시간이고 맥주타임이 기다리고 있기에 이까지 적고 - 
기본적인 웹에서 이미지 불러오는 것을 단계적으로 해결해 나가는 글을 차례로 적어 보렵니다... 

아마.. 다음글은  웹 이미지를 GridView로 불러와 보기 및 문제점 인식이 되겠네요.

Image Cache가 없이는 어떤 앱이든 만들 수가 없어보인다.

부하가 너무 심하다.

이미지 하나를 터치할때마다 request 하는데 이건 cache가 아니고선 정말 답이 없다.

오전 내내 삽질하다가 지금부터 cache를 만들어 볼까나....
View 
- 드로잉 메서드를 가진 Canvas를 제공한다.(onDraw 등)
- 비트맵과 래스터 그래픽스를 가진 비주얼 인터페이스를 만들고, 화면 터치나 키 누름 같은 사용자 이벤트를 재정의하면 상호 작용 할 수 있다.
- 2D를 표현할 시 적합하다.

- onMeasure : 100 x 100 픽셀의 공간에서 자신이 차지할 폭과 높이를 계산한다.
- onDraw : 실제 캔버스에 무언가 그리는 메서드.


SurfaceView
- 백그라운드 스레드에서의 드로잉과 OpenGL을 이용한 3D 그래픽스를 지원한다.
- 자주 업데이트 되거나 복잡한 그래픽 정보를 표시하는 그래픽스 비중이 높은 컨트롤을 위한 옵션이 될 수 있음.


윈도우 서버에서는 보안상 직접적으로 네트워크 드라이브 접근이 허용되지 않는다.

Apache의 Alias를 이용하거나 UNC를 이용해서 접근하거나.. 해야하는데 정말 잘 되지 않더라..

그래서 찾던 도중에 발견한것이 jCIFS - 

  - http://jcifs.samba.org/
  - http://blog.bensmann.com/adding-jcifs-to-javaiofile-for-easy-access-to
  - http://blog.naver.com/ugigi/70088495064

대충 위 사이트 살펴보고 -

jcifs-1.3.14.jar 다운받아 classpath에 넣어주고 - 

시간 관계상 소스만 아래에 던진다.
	String url = "smb://{ip};{user}:{pw}@{ip}/{drive}/{path}/{filename}"
	SmbFile file = new SmbFile(url);
	SmbRandomAccessFile rf = new SmbRandomAccessFile(file, "r");
	byte[] b = new byte[10000];
	int n;
	while(( n = rf.read( b )) > 0 ) {
		System.out.write(b, 0, n);
	}


일반적인 java.util.IO 클래스들 처럼 사용할 수 있다.
단 아쉬운것은 RandomAccessFile에 있는 Chanel이 없어 read() 해야한다는 건데 이는 직접 구현해야한다.
API도 제공하고 있으니 사용하는데 무리는 없었다.

+ Recent posts