관리 메뉴

막내의 막무가내 프로그래밍 & 일상

[안드로이드] 기억노트 - 안드로이드 리스트뷰 (ListView) 공부 기록 본문

안드로이드/자바 & Previous

[안드로이드] 기억노트 - 안드로이드 리스트뷰 (ListView) 공부 기록

막무가내막내 2019. 3. 28. 23:00
728x90

매번 해도 기억이 가물가물한 리스트뷰 기본 사용법을 기록해논다.

아이템-어뎁터-뷰 기억하자.

 

어댑터

package com.example.a82107.mylistview_adapter;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    SingerAdapter adapter;

    EditText editText;
    EditText editText2;

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

        editText = findViewById(R.id.editText);
        editText2 = findViewById(R.id.editText2);

        ListView listView = findViewById(R.id.listView);
        adapter = new SingerAdapter();
        adapter.addItem(new SingerItem("트와이스", "010-2223-1324", R.drawable.a));
        adapter.addItem(new SingerItem("걸스데이", "010-2223-2222", R.drawable.b));
        adapter.addItem(new SingerItem("소녀시대", "010-2223-1333", R.drawable.c));
        adapter.addItem(new SingerItem("와우", "010-2223-1312", R.drawable.z));
        adapter.addItem(new SingerItem("레드벨벳", "010-2223-4141", R.drawable.e));
        adapter.addItem(new SingerItem("블랙핑크", "010-2223-2334", R.drawable.f));
        adapter.addItem(new SingerItem("티아라", "010-2223-7789", R.drawable.g));
        listView.setAdapter(adapter);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                SingerItem item = (SingerItem) adapter.getItem(position);
                Toast.makeText(getApplicationContext(), "선택 : " + item.getName(), Toast.LENGTH_SHORT).show();

            }
        });

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = editText.getText().toString();
                String mobile = editText2.getText().toString();

                adapter.addItem(new SingerItem(name, mobile, R.drawable.b));

                //어탭터 쪽에서 리스트뷰쪽으로 갱신하라고 알려줌
                adapter.notifyDataSetChanged();
            }
        });


    }

    class SingerAdapter extends BaseAdapter {
        ArrayList<SingerItem> items = new ArrayList();

        @Override
        public int getCount() {
            return items.size();
        }

        @Override
        public Object getItem(int position) {
            return items.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        public void addItem(SingerItem item) {
            items.add(item);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            //SingerItemView view  =new SingerItemView(getApplicationContext());

            //위에 대로하면 1000개의 아이템이 다 로딩되면 메모리가 엄청나게 쓰일거다.(뷰객체가 너무많이 만들어주면 메모리를 엄청 소비할 수 있다.)
            //화면에 보이는게 열몇개밖에 안된다고하면 열몇개보다 조금더 많은 수를 만든다음에
            //화면에 보여줬다가 안보여지게 되는 것들은 다시 재사용을 하는거다. (즉 뷰는 그대로고 데이터만 싹싹 바꿔주는것이다.)
            //매개변수에서 convertView라는 것을 이용해 코드를 재사용할 수 있다
            //실제 화면에 그려지는 아이템을 ConvertView 라는 배열로 관리하는데, 화면에 보여지는 만큼 Convert View를 생성하고 스크롤시 View를 재활용하기 때문에 성능면으로 우수한 구조
            //실무에서 위 주석보다 아래처럼 생성을많이함(메모리 효율성을 위해서)
            SingerItemView view = null;
            if (convertView == null) {  //convertView가 null인 경우에만 뷰를 생성해줌( 즉 화면에 띄워질 개수의 리스트뷰 개수만큼 뷰가 만들어지지 않았고 그러므로 아직 재활용할떄가 아니다.) (그러므로 뷰를 생성해준다.)
                view = new SingerItemView(getApplicationContext());
            } else {
                view = (SingerItemView) convertView;  //여기 else문에서의 converView는 이전에 썻던 뷰를 말함.(캐스팅하여 사용했던 뷰를 재사용해준다. 생성X 썻던뷰만 가져와서 밑 코드에서 내용만 바꿔준다 생각)
            }

            SingerItem item = items.get(position);
            view.setName(item.getName());
            view.setMobile(item.getMobile());
            view.setImage(item.getResid());
            return view;
        }
    }
}

 


아이템(데이터) 클래스

package com.example.a82107.mylistview_adapter;

public class SingerItem {
    String name;
    String mobile;
    int resid;

    public SingerItem(String name, String mobile, int resid) {
        this.name = name;
        this.mobile = mobile;
        this.resid = resid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public int getResid() {
        return resid;
    }

    public void setResid(int resid) {
        this.resid = resid;
    }

    @Override
    public String toString() {
        return "SingerItem{" +
                "name='" + name + '\'' +
                ", mobile='" + mobile + '\'' +
                ", resid=" + resid +
                '}';
    }
}

 


package com.example.a82107.mylistview_adapter;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class SingerItemView extends LinearLayout {
    TextView textView;
    TextView textView2;
    ImageView imageView;
    public SingerItemView(Context context) {
        super(context);
        init(context);//이 클래스 생성할때 밑에 singer_item.xml 인플레이트 코드작업해준거 실행해줌으로써
        //인플레이트된 상태이고 xml조작이 가능해짐 (MainActivity에서 이 뷰를 생성하고 xml 이미지뷰나 텍스트뷰에 내용을 삽입한다거나 할수 있어짐.
    }

    public SingerItemView(Context context,  AttributeSet attrs) {
        super(context, attrs);
        init(context); //이 클래스 생성할때 밑에 singer_item.xml 인플레이트 코드작업해준거 실행해줌으로써
                        //인플레이트된 상태이고 xml조작이 가능해짐 (MainActivity에서 이 뷰를 생성하고 xml 이미지뷰나 텍스트뷰에 내용을 삽입한다거나 할수 있어짐.
    }

    //singer_item.xml을 인플레이트해서 받아서 코드작업함
    private void init(Context context){
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.singer_item, this, true);

        textView = findViewById(R.id.textView);
        textView2 = findViewById(R.id.textView2);
        imageView = findViewById(R.id.imageView);
    }

    public void setName(String name){
        textView.setText(name);
    }

    public  void setMobile(String mobile){
        textView2.setText(mobile);
    }

    public  void setImage(int resId){
        imageView.setImageResource(resId);
    }
}

 

 

처음 배울때는

 adapter.notifyDataSetChanged();

이 메소드가 데이터바뀐부분을 적용해서 변경해주는 역할로 알고 2번을 호출한적이 있었는데, 만약 아이템을 1개를 나중에 새로 추가하고 이 메소드를 2번 호출하면 새로추가된 아이템이 2번 추가되므로 유의하도록하자.

 

즉 바뀐부분을 어댑터뷰에 반영해주되 3번을 호출하면 그 바뀐부분을 중복해서 3번을 실행해서 이상해진다.

 

 

 

 

 

728x90
Comments