오늘은 HttpURLConnection 에 대해 포스팅 해보겠다. 


포스팅 하게 된 이유는 저번에 잘 사용하던 httpClient(아파치 라이브러리)가 deprecated 되었기 때문이다.


갑자기 사라져서 당황했었다... 아래 내용은 Google Developer 에서 발췌한 android 6.0 변화에서 httpClient에 대한 이야기다. 


Apache HTTP Client Removal


Android 6.0 release removes support for the Apache HTTP client. If your app is using this client and targets Android 2.3 (API level 9) or higher, use the HttpURLConnection class instead. This API is more efficient because it reduces network use through transparent compression and response caching, and minimizes power consumption. To continue using the Apache HTTP APIs, you must first declare the following compile-time dependency in your build.gradle file:

android {
    useLibrary
'org.apache.http.legacy'
}


요약하자면, 위와 같이 gradle에 해당 라이브러리를 추가하면 httpClient 쓸수는 있다. 또 말하기를, httpClient의 기능은 많지만 무겁다, 


그리고 안드로이드에서는 조금 오바(?)스러운 httpClient보다는,


안드로이드에 적합한 API인 HttpURLConnection을 사용하라는 이야기다.(해당 이슈는 예전부터 나오던 이슈긴 하다.)


뭐.. httpClient가 편리하지만 저렇게 권장하지 않는 API를 쓰기에는 유지보수와 기능에 문제가 있다고 판단, 바로 HttpURLConnection으로 옮겼었다.


서론은 여기까지 하고, 시작해 보자. HttpURLConnection도 굉장히 쉽다.


먼저 인터넷 환경이 필요한 작업이므로 AndroidManifest.xml 파일에 


<uses-permission android:name="android.permission.INTERNET"/> 을 작성해 인터넷 환경을 만들어준다.


이제 MainActivity에 네이버의 웹 정보를 받아오는 코드를 작성해보자.


new AsyncTask<Void,Void,Void>(){
@Override
protected void onPreExecute() {
super.onPreExecute();
strUrl = "http://www.naver.com"; //탐색하고 싶은 URL이다.
}

@Override
protected Void doInBackground(Void... voids) {
try{
Url = new URL(strUrl); // URL화 한다.
HttpURLConnection conn = (HttpURLConnection) Url.openConnection(); // URL을 연결한 객체 생성.
conn.setRequestMethod("GET"); // get방식 통신
conn.setDoOutput(true); // 쓰기모드 지정
conn.setDoInput(true); // 읽기모드 지정
conn.setUseCaches(false); // 캐싱데이터를 받을지 안받을지
conn.setDefaultUseCaches(false); // 캐싱데이터 디폴트 값 설정

strCookie = conn.getHeaderField("Set-Cookie"); //쿠키데이터 보관

InputStream is = conn.getInputStream(); //input스트림 개방

StringBuilder builder = new StringBuilder(); //문자열을 담기 위한 객체
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"UTF-8")); //문자열 셋 세팅
String line;

while ((line = reader.readLine()) != null) {
builder.append(line+ "\n");
}

result = builder.toString();

}catch(MalformedURLException | ProtocolException exception) {
exception.printStackTrace();
}catch(IOException io){
io.printStackTrace();
}
return null;
}

@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
System.out.println(result);
}
}.execute();

AsynTask는 통신을 할 때 필요한 클래스이다. 이해하면 사용하기 쉽지만, 모르는 사람은 일단 따라 써보기로 하자.


protected void onPreExecute() 메서드 안에는 통신을 하기전 필요한 정보를 셋팅하는 구간이다.


우리가 탐색할 네이버 주소를 적었다.


protected Void doInBackground(Void... voids) 이 메서드가 실제로 통신 할때 작동하는 부분이다.


왠만한 설명은 주석처리 해놨다. 좀더, 정리를 해주자면..


Url = new URL(strUrl); // URL화 한다.
HttpURLConnection conn = (HttpURLConnection) Url.openConnection(); // URL을 연결한 객체 생성.


이 부분이 해당 URL(예시는 네이버)의 정보를 담고 있는 객체를 생성하는 부분이다.


conn.setRequestMethod("GET"); // get방식 통신
conn.setDoOutput(true); // 쓰기모드 지정
conn.setDoInput(true); // 읽기모드 지정
conn.setUseCaches(false); // 캐싱데이터를 받을지 안받을지
conn.setDefaultUseCaches(false); // 캐싱데이터 디폴트 값 설정


이 부분이 해당 통신을 위한 셋팅 부분이다. HttpURLConnection은 스트림 기반이라 셋팅 할 것이 많다.


strCookie = conn.getHeaderField("Set-Cookie"); //쿠키데이터 보관

이 부분은 세션지정을 위한 쿠키값 저장을 하는 부분이다.


httpClient는 쿠키값을 알아서 저장해줬지만 HttpURLConnection은 따로 저장 관리를 해줘야한다.


InputStream is = conn.getInputStream(); //input스트림 개방

StringBuilder builder = new StringBuilder(); //문자열을 담기 위한 객체
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"UTF-8")); //문자열 셋 세팅
String line;

while ((line = reader.readLine()) != null) {
    builder.append(line+ "\n");
}

 이 부분은 웹 정보를 파싱하는 부분이다. 중요한 점은 웹 정보 마다 다른 문자열 셋일 수 있으므로 맞는 문자열 셋팅을 해줘야 한다.


protected void onPostExecute(Void aVoid)

이 메서드 부분이 해당 통신이 끝난 후 통신작업이 아닌 마무리 작업(UI작업, 사용자 정의 작업 등)을 하는 부분이다.


예시에서는 콘솔에 출력하는 메서드를 썻다.


실행해보면 네이버의 정보를 콘솔에 출력하는 것을 볼 수 있다.


oRTK : { "t": "2015-11-17T12:25Z", "s": "2015.11.17. (화) 12:25 PM", "d": [ { "k": "오마이비너스", "c": "up", "a": "상승", "n": "72" }, 

{ "k": "신민아", "c": "up", "a": "상승", "n": "99" }, { "k": "진세연", "c": "up", "a": "상승", "n": "225" }, 

{ "k": "이정재", "c": "up", "a": "상승", "n": "216" }, { "k": "육룡이 나르샤 결방", "c": "up", "a": "상승", "n": "174" }, 

{ "k": "다이나믹듀오", "c": "up", "a": "상승", "n": "216" }, { "k": "풍선껌", "c": "up", "a": "상승", "n": "63" }, 

{ "k": "첼시 리", "c": "up", "a": "상승", "n": "348" }, { "k": "먹는존재", "c": "up", "a": "상승", "n": "150" }, 

{ "k": "명지전문대", "c": "up", "a": "상승", "n": "93" } ] },


콘솔에 찍힌 정보 중간에 실시간 검색어 정보를 발견했다. (실시간 정보는 네이버에서 제공하는 API가 있다.)


시간대가 틀려 찍히는 정보가 틀리겠지만... 무튼 성공 한걸 알 수 있다.


해당 예시는 get 방식으로 웹 정보를 받아오는 방식이다.


추후에 post방식으로 웹 정보를 이용하는 방법도 포스팅 하겠다.



해당 프로젝트는 https://github.com/Mommoo/ExampleCode/tree/master/HttpURLConnection 에서 받을 수 있다.






포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee
  1. serfe112 2017.07.10 15:30

    감사합니다. 이해하기 쉽네요 ㅎㅎ

  2. secc 2018.07.31 14:49

    감사합니다 자세하고 읽기 쉽네요 ㅎ




리눅스 서버를 구축한 후, Mysql 데이터베이스 환경을 만들었다.


Java로 서버연동을 해보려고 했지만, 잘 되지 않았다.


이유는 간단 했다. 데이터베이스를 초기에 만들때 접근 사용자 셋팅은 외부접근을 허용하지 않기 때문이다.


이유를 알았으니, 해결해보자.


GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';


위의 명령어를 실행 했을 경우, root 사용자는 모든호스트(%)에게 모든 권한을 허용하겠다는 의미이다.


조금더 응용해서 특정 IP 대역만을 허용하고 싶다 하면,


GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.%';


이런식으로 명령어를 써주면 되겠다. 192.168로 시작하는 IP대역의 외부접근을 허용하겠다는 의미이다.


권한설정후 Java로 연동해보니 잘 되었다.



포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee



이번 포스팅은 자바의 생성자(constructor)에 관해 알아보자.


생성자는 자바뿐만 아니라 객체지향언어의 중요한 구조이기 때문에, 자바에 국한짓지 말고, 크게 이해하면 좋다.


생상자의 구조를 자바언어를 통해 설명하고자 한다.


먼저, 하나의 변수를 사용한다고 가정 해보자.


 int a; 



위의 선언한 int형 변수 a는 의미가 있는가? 


답은 No이다. 이유는 초기화를 하지 않았기 때문이다.


int a=10;


위와 같이 초기화 해야 비로소 변수 a는 상수 10을 가리키는 변수가 된 것이다. 


이렇게 의미있는 데이터를 넣는것 을 자바에서는 초기화라고 명명한다.


그렇다면, 하나의 클래스(class)를 사용 한다고 가정 해보자. 


위의 예시 처럼 의미있는 클래스를 만들기 위해 서는 초기화 작업을 거쳐야 할 것이다.


그렇다면 무엇을 초기화 해야할까? 라는 질문에 봉착한다.


클래스는 크게 나누자면 멤버변수 와 메서드 이다.


class Test{

    public int num;
    public String str;
    
    public Test(int num,String str){
        this.num = num;
        this.str = str;    
    }

    public void print(){
        System.out.println("num은"+num+"입니다. , str은"+str"입니다.");
    }
}

     위의 예시는 3번,4번이 멤버변수 , 6~9번,11~13번 까지가 메서드 이다. 


이러한 클래스를 초기화 하려고 한다. 예시 클래스에서 초기화 하는 메서는 Test 메서드이다.


매개변수로 num 과 str 을 받아 클래스의 멤버변수에 값을 넣는 메서드이다. 앞에 this 를 붙여주면 클래스 안의 멤버변수 str을


안붙여주면 매개변수로 받는 str을 의미한다.( 변수의 이름이 같을 경우 구분짓기 위해 this를 쓴다.)


이 메서드는 특이하게 Test 클래스의 이름과 똑같은 Test이름을 가지는 메서드인데,


이러한 메서드를 우리는 생성자라고 부른다.


생성자는 특이하게 함수의 리턴형이 존재 하지 않고 앞서 쓴 예시와 같이 클래스의 이름과 같다.


클래스는 이러한 생성자를 토데로 초기화를 한다. 물론 꼭 생성자를 통해서 멤버변수를 초기화하지 않아도 된다.


하지만, 보통은 생성자를 통해 클래스의 필요한 정보를 초기화 한다 정도만 알면 되겠다.





다음 포스팅은 생성자를 어떻게 사용하는지, 생성자에 관해 좀더 자세히 다루겠다.




'Java' 카테고리의 다른 글

JAVA Static이란?  (2) 2016.03.29
자바 enum 열거형  (0) 2016.01.27
JAVA - 익명클래스(Anonymous class)란?  (3) 2016.01.20
JAVA의 삼항연산자  (4) 2015.12.11
JAVA의 생성자 (2)  (2) 2015.11.17

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee




http://mommoo.tistory.com/1 ( RecyclerView , CardView 사용하기.(1) )




2편이다. 처음 읽는 독자는 위의 경로의 포스팅을 먼저 읽기를 권한다.


RecyclerView에 필요한 Adpater를 선언할 것이다.

참조한 구글 문서는 단순히 TextView만을 이용한 예제이다.


본 게시물은 추가적으로 image를 넣어 image와 text로 구성된 예제임을 밝힌다.



MyAdapter.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private ArrayList<MyData> mDataset;
 
    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    public static class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case 
        public ImageView mImageView;
        public TextView mTextView;
 
        public ViewHolder(View view) {
            super(view);
            mImageView = (ImageView)view.findViewById(R.id.image);
            mTextView = (TextView)view.findViewById(R.id.textview);
        }
    }
 
    // Provide a suitable constructor (depends on the kind of dataset)
    public MyAdapter(ArrayList<MyData> myDataset) {
        mDataset = myDataset;
    }
 
    // Create new views (invoked by the layout manager)
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext())
                               .inflate(R.layout.my_view, parent, false);
        // set the view's size, margins, paddings and layout parameters
        ...
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }
 
    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        holder.mTextView.setText(mDataset.get(position).text);
        holder.mImageView.setImageResource(mDataset.get(position).img);
    }
 
    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDataset.size();
    }
}
 
class MyData{
    public String text;
    public int img;
    public MyData(String text, int img){
        this.text = text;
        this.img = img;
    }
}
cs



MyAdpater.class를 선언하고, RecyclerView.Adapter를 상속 받았다.


MyAdpater안에 직접 구현한 ViewHolder 클래스를 제네릭으로 받는 구조이다.  물론 직접 만드는 ViewHolder도 


ReclerView.ViewHolder를 상속받아야 한다.


(ViewHolder는 ListView를 사용할 당시, RecylerView처럼 View를 효율적으로 쓰기 위한 디자인 패턴중 하나였다. 

리소스를 제법 잡어먹는 findViewById()를 적게 호출하기 위함이다. RecyclerView 에서는 적극적으로 ViewHolder 패턴을 사용하라고 권장한다. )


ViewHolder 클래스는 RecyclerView의 item에 들어갈 view를 받은후 그 view 안에 있는 ImageView와 TextView를 초기화 한다.


그다음은 MyAdapter 생성자가 보이는데, 매개변수로 ArrayList<MyData> 객체를 받는다. MyData 클래스는 data-set을 위한 클래스로


해당 예제에 맨 아래에 생성했다.




중요한 내용은 지금부터이다.


onCreateViewHolder 메서드안의 내용을 잘 바꾸어야 내가 원하는 결과물이 나온다.


첫번째로, View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_view, parent, false); 는


앞서 말한 ViewHolder에 넣어줄 view를 찾는 과정이다. my_view라는 xml에는 cardview가 들어갈 예정이다.


이 view를 넣기위한 ViewHolder를 다음과 같이 선언한 후 넣는다.


 ViewHolder vh = new ViewHolder(v);


그다음 onBindViewHolder 메서드를 보자. 이 메서드는 RecyclerView의 item의 셋팅과 사용자가 스크롤링 할때, 호출되는 메서드이다.


우리가 원하는 데이터가 포지션별로 ArrayList<MyData>에 저장되어 있다. 이러한 데이터를 포지션별로 보여주는 것을 보장해준다.


마지막으로 MyData 클래스이다. 우리가 원하는 image와 text 데이터를 보관하기 위한 데이터 저장소 개념으로 보면 된다.



다음은 위에서 소개한 my_view.xml을 코딩 해보자.



my_view.xml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.v7.widget.CardView
        android:id="@+id/cardview"
        card:cardCornerRadius="3dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
        <ImageView
            android:scaleType="fitXY"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:id="@+id/image"/>
        <TextView
            android:id="@+id/textview"
            android:gravity="center|left"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="10dp"/>
        </LinearLayout>
    </android.support.v7.widget.CardView>
</RelativeLayout>
cs



위의 CardView 위젯을 보면 android: 대신 card: 인자가 보이는데, 


이 인자는 부모뷰에 xmlns:card="http://schemas.android.com/apk/res-auto"


등록을 해주면 된다. cardCornerRadius 값은 모서리 둥근 정도를 결정한다.


해당 카드뷰 view 아래는 데이터를 보여줄(image,text) 하위 view들을 지정했다.


cardview 자체는 FrameLayout를 상속 받기 때문에 따로 LinearLayout을 선언하여 수직 정렬 하였다.


다 끝났다. 이제 MyActivity로 돌아가 데이터를 넣어본다.



MyActivity.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class MyActivity extends Activity {
    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;
    private ArrayList<MyData> myDataset;    
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity);
        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
 
        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);
 
        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);
 
        // specify an adapter (see also next example)
        myDataset = new ArrayList<>();
        mAdapter = new MyAdapter(myDataset);
        mRecyclerView.setAdapter(mAdapter);
        
        myDataset.add(new MyData("#InsideOut", R.mipmap.insideout));
        myDataset.add(new MyData("#Mini", R.mipmap.mini));
        myDataset.add(new MyData("#ToyStroy", R.mipmap.toystory));
 
    }
    ...
}
cs


컴파일을 해보면...




멋진 카드효과와 함께 잘 나온다.


해당 프로젝트는 https://github.com/Mommoo/ExampleCode/tree/master/RecyclerView  에서 받을 수 있다.




포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee
  1. femto 2016.07.20 18:23

    리싸이클뷰와 카드뷰에 대하여
    자세한 설명 감사합니다.
    정말 감사합니다.

  2. Squat 2016.10.11 21:39 신고

    정말 좋은 게시물이네요.
    많은 도움이 되었습니다. 감사합니다^^

  3. 김병희 2016.11.12 19:05

    myDataset 선언은 소문자, 초기화는 대문자로 되어 있네요 ...
    두 편 다 잘 보았습니다.
    감사합니다.

    • Mommoo 2016.11.13 20:07 신고

      오타 찾아주셔서 감사합니다..!
      읽어주셔서 감사합니다 ^^!

  4. 김병희 2016.11.12 19:25

    질문 있습니다.
    얼른 봐서 못 찾았는데,
    가로로 스크롤시키는 방법 - 어떻게 하면 되나요?

  5. 김병희 2016.11.12 22:58

    위 질문은 구글해서 답을 찾았습니다.
    RecyclerView 아이템 선택(클릭)했을 때 선택된 아이템을 하이라이트시키는 방법은 없을까요?
    OnClickListener에서 처리하려다가 실패했습니다.
    도와주시면 고맙겠습니다.

    • Mommoo 2016.11.13 20:05 신고

      몇가지 방법중
      ViewHolder 생성자안에서,
      View 자체에 OnClickListener을 생성하는 방법이 있습니다.^^
      아래의 코드를 참고 하세요.

      view.setOnClickListener(new View.OnClickListener(){
      @Override
      public void onClick(View view){
      int position = MyAdapter.getAdapterPosition();
      System.out.println("position : ' + position +" 번 입니다. ");
      }
      }

  6. 김병희 2016.11.19 00:15

    답변을 늦게 보았습니다.
    getView 메소드 사용과 같은 것으로 생각되는군요.
    감사합니다.

  7. 123 2016.12.02 20:02

    Mydataset부분이 왜에러일까요...

    • Mommoo 2016.12.02 23:10 신고

      해당 코드는 정상 실행되는코드 입니다! 다시한번 차근차근 따라해보시거나,
      깃허브에 올려둔 소스코드를 실행해보는게 어떨까요?

  8. 오소리 2017.01.04 23:02

    블로그 잘 보고있습니다. 질문이 있는데 카드뷰 레이아웃에서 최상위 레이아웃을 릴레이티브에에서 리니어로 바꾸면 weight를 최대크기로 해놓아도 안에 들어가는 내용물의 크기로 맞추어집니다. 왜 이럴까요?

    • Mommoo 2017.01.04 23:04 신고

      잘 읽어주셔서 감사합니다. 해당 부분의 코드를 올려주시면 증상이 무엇인지 확인해드릴수 있을거 같습니다!

  9. itba 2017.01.25 14:26

    댓글보고 질문이 있는데요. 아이템하나하나에 클릭을 하려는데

    view.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
    int position = MyProfileAdapter.getAdapterPosition();

    }
    });
    에서 getAdapterPosition이 인식되지 않습니다. 님 글보고 다 따라한건데도 안되네요 ㅠ

    • Mommoo 2017.01.25 15:49 신고

      해당 패턴은 ViewHolder가 가지고 있는 getAdapterPosition()을 사용하는데요,

      MyProfileAdapter.getAdapterPosition();
      로 작성하지 마시구용,

      ViewHolder 클래스 내부에서

      int position = 뷰홀더클래스명.this.getAdapterPosition()으로 작성해보세요.

  10. 은이 2017.03.23 12:22

    잘 읽고 따라했더니 실행이 잘되네요!!
    그런데 list안 card의 내용이 page당 한개씩 생성되어 한 페이지에 여러개가 동시에 생성되지 않습니다. 이런 문제는 어떻게 해결해야 할까요?

    • Mommoo 2017.03.23 12:33 신고

      읽어주셔서 감사합니다.^^ page는 viewpager말씀이신가요?? 정확히 무얼 말하는지 잘 모르겠네요
      만약 뷰페이저 마다 리스트를 쓰고싶다면 각 페이저마다 리싸이클러뷰는 반드시 있어야 하구요.
      작성하신 MyAdapter객체를 각 리사이클러뷰에 setAdapte메서드로 연결해주셔야 합니다.

    • 오클라호마호 2018.01.02 20:42 신고

      android:layout_height 항목을 "wrap_content"로 한번 변경해보세요.

  11. 왕십리공머생 2017.05.10 11:58

    포스팅 참고해서 실행완료했습니다!
    궁금한 점은drawable을 받으실때 int 타입을 쓴이유가 궁급합니다!

    • Mommoo 2017.05.12 09:17 신고

      읽어주셔서 감사합니다..^^
      drawable을 받은게 아닙니다.
      ImageView에 Image를 넣기위해서는
      몇가지 방법이 있는데 그 중,
      이미지 리소스 id를 넣는 방법이 있습니다.
      (setImageResource) 안드로이드 에서 리소스 관리는 자료형이 int형이므로, 그에 맞게 int 형으로 받았습니다...^^

    • 왕십리공머생 2017.05.13 20:30

      아~ 명쾌한 답변 감사드립니다!

  12. 미니타임 2018.01.12 19:05 신고

    안녕하세요..
    비슷한 예제로 공부중에 있는 프로그래밍 완전 초보입니다..
    사용자 정보들을 파이어베이스 리얼데이터베이스에서 받아와 onBindViewHolder에서 뷰에 나타나게 되는데
    얘네들을 스코어 순서대로 정렬하려고 하는데 어떻게 해야할지 모르겠네요..
    사용자들이 가지고 있는 스코어를 높은 순서대로 정렬시키려면 어떻게 하면 될까요?

    • Mommoo 2018.08.03 12:27 신고

      너무 늦게 봤네요 T^T
      죄송합니다..
      다른 질문 있으시면 언제든지 해주세요!!

  13. ㅇㅇ 2018.04.23 19:55

    많은 도움이 됐어요 감사합니다 :)

  14. GAMSA 2019.08.05 10:34

    덕분에 카드 리스트뷰 쉽게 구현할 수 있었습니다.
    감사드립니다^^ 애드센스 눌러 드렸어요

  15. 초보코딩 2019.10.02 15:29

    안녕하세요
    공부하면서 코딩중인 학생입니다.
    우선 게시글 감사히 잘봤습니다 ㅜ ㅜ
    그런데 깃 코드중에
    @strings/appbar_scrolling_view_behavior이 없는데
    혹시 따로 만드신 것인지 여쭤보고 싶습니다.

    • 초보코딩 2019.10.02 16:05

      strings자체가 없어서
      기본적으로 있는
      action_settings을 활용,
      app:layout_behavior="@string/action_settings"로 하여 실행을 완료했습니다.
      근데 예제로 보여주신것처럼 붙어서 보여지지가 않네요..ㅜㅜ string속성값이 달라서 그런건가요 ??




항상 ListView 로만 코딩을 해오다가,


ListView보다 성능과 퍼포먼스가 더 좋다고 하는 RecyclerView, CardView를 사용해보려 한다.


android developer의 training에 올라온 게시글로 사용법을 익혀보자.



The RecyclerView widget is a more advanced and flexible version of ListView

This widget is a container for displaying large data sets that can be scrolled very efficiently by maintaining a limited number of views. 

Use the RecyclerViewwidget when you have data collections whose elements change at runtime based on user action or network events.



어렵지 않은 내용이다. 요약하자면 Listview 보다 성능적으로 좋고, RecyclerView는 최소한의 View 만으로도 큰 데이터를 효율적으로 스크롤링 해준다


또한, 사용자의 입장에서 시시각각 데이터가 변화할때(사용자의 액션을 처리하거나, 네트워크 처리등) 사용하기를 권장한다고 적혀있다.



The RecyclerView class simplifies the display and handling of large data sets by providing:

  • Layout managers for positioning items
  • Default animations for common item operations, such as removal or addition of items

You also have the flexibility to define custom layout managers and animations for RecyclerView widgets.



요약하자면, RecyclerView는 기본적으로 LayoutManager를 사용하여 item을 관리하고, 


사용자입장에서 item의 변화(삭제 되거나 추가등)를 느낄 수 있도록, 기본 애니메이션이 있다고 한다. 


또한, LayoutManager를 사용하여 효과적으로 item의 정렬 과 애니메이션등을 다룰 수 있다고 한다.


중요한것은,  Adapter를 통해 data를 RecyclerView에 연결시킨다. 

(RecyclerView는 데이터를 사용자에게 어떻게 보여줄지 그림담당만 한다.)


RecyclerView에 대한 설명은 이정도로 충분하다. (더 자세한 설명을 알고 싶다면, http://developer.android.com/training/material/lists-cards.html 을 참고)


이번엔 CardView에 대해 간단히 설명 하자면, 


Card모양의 View이다. 즉, 예전에는 custom 하여 card모양을 흉내냈지만, CardView가 나옴으로써 좀더 쉽게 card를 표현 할 수 있다.


(material 디자인에 맞게, 그림자와 클릭 효과등을 지정 할 수 있다.) 이러한 view를 RecyclerView와 함께 사용할 것이다. 


좀더 세부적으로 설명하자면, 


ListView 에는 각각 item들이 차지하는 view 의 공간이 있다. 이 공간을 사용자 입맛에 맞게 커스텀하여 데이터를 표현하는 것이다.


RecyclerView에서는 위와 같은 공간을 CardView로 붙일 것이다.



 

이제 직접 코딩을 해보자. 생각보다 간단하다.


먼저, 해당 위젯을 쓰기 위해서는 라이브러리가 필요하다. (안드로이드 스튜디오 기준.)



dependencies {
   
...
    compile
'com.android.support:cardview-v7:21.0.+'
    compile
'com.android.support:recyclerview-v7:21.0.+'
}



해당 프로젝트 graddle에 추가한다. 그 다음으로, layout 폴더에  my_activity를 만들고 아래와 같이 작성한다.


<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
   
android:id="@+id/my_recycler_view"
   
android:scrollbars="vertical"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"/>



위에서 설명했듯이, RecyclerView에는 LayoutManager가 필요하다. 아래의 코딩을 보자.(MyActivity.java)


public class MyActivity extends Activity {
   
private RecyclerView mRecyclerView;
   
private RecyclerView.Adapter mAdapter;
   
private RecyclerView.LayoutManager mLayoutManager;

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
        setContentView
(R.layout.my_activity);
        mRecyclerView
= (RecyclerView) findViewById(R.id.my_recycler_view);

       
// use this setting to improve performance if you know that changes
       
// in content do not change the layout size of the RecyclerView
        mRecyclerView
.setHasFixedSize(true);

       
// use a linear layout manager
        mLayoutManager
= new LinearLayoutManager(this);
        mRecyclerView
.setLayoutManager(mLayoutManager);

       
// specify an adapter (see also next example)
        mAdapter
= new MyAdapter(myDataset);
        mRecyclerView
.setAdapter(mAdapter);
   
}
   
...
}



어렵지 않다. 위에서 설명한데로 RecyclerView의 객체인 mRecyclerView를 선언한후,


item정렬을 위한 LayoutManager를 LinearLayoutManager로 사용한다.(Linear 이므로 아이템이 수직,수평으로 배치 될 것이다.)


데이터와 RecyclerView를 연결 시키기 위한 adpaer로 MyAdapter를 선언하였다. 


이러한 LayoutManager와 Adapter를 setLayoutManager 와 setAdapter 메서드로 셋팅한다.


여기까지 했다면, MyAdapter에 빨간줄이 들어올 것이다.(아직 선언 하지 않았으니까....)


다음 포스팅때 마저 하도록 하겠다.






포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee
  1. Squat 2016.10.11 21:41 신고

    추천!

+ Recent posts