상세 컨텐츠

본문 제목

[안드로이드] List 만들어 보기 [RecyclerView, SQLiteOpenHelper, AlertDialog]

안드로이드

by aries574 2020. 6. 1. 18:17

본문


안드로이드에서 리스트를 만들때 주로 사용하는게 RecyclerView 입니다.

리스트의 데이터를 담기 위해서 DB를 사용할 것이며,  SQLiteOpenHelper 입니다.

마지막으로 리스트의 아이템을 삭제하기 위해서 AlertDialog를 이용하여 다이얼로그 창을 만들 것입니다. 

완성화면입니다.

 

 

사용자를 등록하고, 리스트로 뿌려주며, 삭제까지 가능한 앱을 만들어 보겠습니다. 

 

1. Gradle Scripts -> build.gradle(Module:app) 라이브러리 추가하기

 

implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.android.support:design:28.0.0'

맨 왼쪽 씽크 버튼을 클릭해서 동기화를 해줍니다.

 

2. 메인화면에 올라갈  2개의 화면(입력화면, 리스트화면)를 프래그먼트(Fragment)을 만들겠습니다.

app(마우스오른쪽) -> New -> Fragment -> Fragment(Blank)

 

 

 

Fragment Name 에 파일명을 입력하고, Finish 버튼을 클릭하면 자동으로 java파일과 xml 파일이 생성됩니다.

 

InsertFragment, ListFragment 을 만들면 됩니다.

 

 

 

3. 프래그먼트 화면 작성(Fragment를 생성하면 자동으로 xml파일도 생성이 됩니다.)

fragment_insert.xml (등록화면)

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".InsertFragment">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="아이디:"/>

        <EditText
            android:id="@+id/eId"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="아이디"
            />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="이름:"/>

        <EditText
            android:id="@+id/eName"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="이름"
            />
    </LinearLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:orientation="horizontal"/>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="나이:"/>

        <EditText
            android:id="@+id/eAge"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:hint="나이" />
    </LinearLayout>

    <Button
        android:id="@+id/insertBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="등록"/>

</LinearLayout>

 

fragment_list.xml (리스트화면)

 

 

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".ListFragment" >

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="리스트 화면" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycleView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        />
</LinearLayout>

 

fragment_list.xml 안에 들어가는 리스트 화면을 추가로 생성해줍니다.

 

res -> layout -> user_item.xml

 

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <androidx.cardview.widget.CardView
        android:id="@+id/cardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FFFFFF"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="2dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="2dp"
        app:cardElevation="5dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:orientation="horizontal">
                <TextView
                    android:id="@+id/tId"
                    android:layout_width="120dp"
                    android:layout_height="wrap_content"
                    android:gravity="right"
                    android:text="아이디"
                    android:textStyle="bold"
                    android:textColor="#0E0505"
                    android:textSize="20sp" />
                <TextView
                    android:id="@+id/tName"
                    android:layout_width="120dp"
                    android:layout_height="wrap_content"
                    android:text="이름"
                    android:gravity="right"
                    android:textColor="#0E0505"
                    android:textStyle="bold"
                    android:textSize="20sp" />

                <TextView
                    android:id="@+id/tAge"
                    android:layout_width="120dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="나이"
                    android:gravity="right"
                    android:textColor="#0E0505"
                    android:textStyle="bold"
                    android:textSize="20sp" />
            </LinearLayout>

        </LinearLayout>
    </androidx.cardview.widget.CardView>

</LinearLayout>

 

4. 프래그먼트 소스작성(java)

InsertFragment.java

 

import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;


public class InsertFragment extends Fragment {

    private EditText eId;   //아이디
    private EditText eName; //이름
    private EditText eAge;  //나이

    DBHelper dbHelper;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment_insert, container, false);

        dbHelper = new DBHelper(getActivity().getApplicationContext(), "USER_INFO.db", null, 1);

        eId     = rootView.findViewById(R.id.eId); //아이디
        eName   = rootView.findViewById(R.id.eName); //이름
        eAge    = rootView.findViewById(R.id.eAge); //나이

        //등록버튼
        Button insertBtn = rootView.findViewById(R.id.insertBtn);
        insertBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //DB저장

                String id = eId.getText().toString();
                String name = eName.getText().toString();
                String age = eAge.getText().toString();

                if(id.equals("") || name.equals("") || age.equals("")){
                    Toast.makeText(getContext(), "입력을 다 해주세요", Toast.LENGTH_SHORT).show();
                }else{

                    dbHelper.insert(id, name, age); //DB등록
                    Toast.makeText(getActivity(), "저장되었습니다.", Toast.LENGTH_SHORT).show();
                    reset(); //입력창 초기화
                }
            }
        });

        return rootView;
    }

    /**
     * 입력창 초기화
     */
    public void reset()
    {
        eId.setText(""); //아이디 초기화
        eName.setText("");//이름 초기화
        eAge.setText(""); //나이 초기화
    }
}

 

ListFragment.java

import android.database.Cursor;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;


public class ListFragment extends Fragment {

    RecyclerView recycleView;
    private UserAdapter adapter;

    TextView tId;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment_list, container, false);

        LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);

        recycleView = rootView.findViewById(R.id.recycleView);

        //recycleView 레이아웃 설정
        recycleView.setLayoutManager(layoutManager);

        //recycleView 어뎁터 설정
        adapter = new UserAdapter();
        recycleView.setAdapter(adapter);

        tId = rootView.findViewById(R.id.tId);

        getUserList(); //사용자 리스트 가져오기


        return rootView;
    }

    /**
     * 사용자리스트 가져오기
     */
    private void getUserList(){

        println("<<< getUserList() >>>");

        adapter.removeAllItem();

        final DBHelper dbHelper = new DBHelper(getActivity().getApplicationContext(), "USER_INFO.db", null, 1);

        Cursor cursor = dbHelper.getUserList();

        int count = 0;

        while (cursor.moveToNext()) {
            UserVo vo = new UserVo();
            vo.setId(cursor.getString(0));
            vo.setName(cursor.getString(1));
            vo.setAge(cursor.getString(2));
            adapter.addItem(vo);
            count++;
        }

        adapter.notifyDataSetChanged();
        println("회원수:: " + adapter.getItemCount());
    }

    public void println(String msg){
        Log.d("listFragment", msg);
    }
}

5. 데이터를 관리할 DBHelper.java 생성

app> java -> 프로젝트명(마우스오른쪽) -> New -> Java Class

 

 

 

클래스명은 DBHelper로 했습니다.

 

public class DBHelper extends SQLiteOpenHelper {

    // DBHelper 생성자로 관리할 DB 이름과 버전 정보를 받음
    public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    /**
     * 테이블 생성
     * @param db
     */
    @Override
    public void onCreate(SQLiteDatabase db) {

        db.execSQL("CREATE TABLE USER_INFO (_num INTEGER PRIMARY KEY AUTOINCREMENT, id TEXT, name TEXT, age TEXT );");
    }

    // DB 업그레이드를 위해 버전이 변경될 때 호출되는 함수
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    /**
     *  등록
     * @param  id 아이디
     * @param name 이름
     * @param age 나이
     */
    public void insert(String id, String name, String age) {
        // 읽고 쓰기가 가능하게 DB 열기
        SQLiteDatabase db = getWritableDatabase();

        // DB에 입력한 값으로 행 추가
        db.execSQL("INSERT INTO USER_INFO VALUES(null, '" + id + "',   '" + name + "', '" + age + "');");
        db.close();
    }

    /**
     * 수정
     * @param id 아이디
     * @param age 나이
     */
    public void update(String id, int age) {
        SQLiteDatabase db = getWritableDatabase();
        // 입력한 항목과 일치하는 행의 가격 정보 수정
        db.execSQL("USER_INFO USER_INFO SET age='" + age + "' WHERE id='" + id + "';");
        db.close();
    }

    /**
     * 삭제
     * @param id 아이디
     */
    public void delete(String id) {
        SQLiteDatabase db = getWritableDatabase();
        // 입력한 항목과 일치하는 행 삭제

        db.execSQL("DELETE FROM USER_INFO WHERE id='" + id + "';");
        db.close();
    }

    /**
     * 조회
     * @return
     */
    public Cursor getUserList() {
        // 읽기가 가능하게 DB 열기
        SQLiteDatabase db = getReadableDatabase();
        String result = "";

        // DB에 있는 데이터를 쉽게 처리하기 위해 Cursor를 사용하여 테이블에 있는 모든 데이터 출력
        Cursor cursor = db.rawQuery("SELECT id, name, age FROM USER_INFO ORDER BY id", null);

        return cursor;
    }
}

 

 

6. 메인화면에 탭을 만든 후  앞에서 만든 2개의 화면(입력화면, 리스트화면)을  적용하겠습니다.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginBottom="10dp"
        app:tabMode="fixed"
        app:tabGravity="fill"
        app:tabTextColor="@color/colorAccent"
        android:elevation="1dp"
        />

    <FrameLayout
        android:id="@+id/containers"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</LinearLayout>

 

7. MainActivity.java

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import android.graphics.Color;
import android.os.Bundle;
import com.google.android.material.tabs.TabLayout;

public class MainActivity extends AppCompatActivity {

        InsertFragment insertFragment; //입력 프래그먼트
        ListFragment listFragment; //리스트 프래그먼트
        TabLayout tabs;

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

            //프래그먼트 초기화
            insertFragment = new InsertFragment(); //입력 화면
            listFragment = new ListFragment(); // 리스트 화면

            //기본 프래그먼트 설정(첫 화면은 리스트화면)
            getSupportFragmentManager().beginTransaction().replace(R.id.containers, listFragment).commit();

            //탭에 화면 추가
            tabs = findViewById(R.id.tabs);
            tabs.addTab(tabs.newTab().setText("정보 리스트"));
            tabs.addTab(tabs.newTab().setText("정보 등록"));

            tabs.setTabTextColors(Color.rgb(0,0,0),Color.rgb(255,0,0)); //기본색상, 선택시색상

            //탭 선택시 사용하는 이벤트리스너
            tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener(){
                @Override
                public void onTabSelected(TabLayout.Tab tab) {

                    //선택된 탭 위치

                    int position = tab.getPosition();

                    Fragment selected = null;

                    if(position == 0) //정보등록탭을 선택하면
                    {
                        selected = listFragment;

                    }else if(position == 1) // 정보 리스트탭을 선택하면
                    {

                        selected = insertFragment;
                    }

                    getSupportFragmentManager().beginTransaction().replace(R.id.containers, selected).commit();
                }

                @Override
                public void onTabUnselected(TabLayout.Tab tab) {

                }

                @Override
                public void onTabReselected(TabLayout.Tab tab) {

                }
            });
        }
}

 

 

8. 화면과 데이터를 연결해줄 UserAdapter를 생성하겠습니다.

UserAdapter.java

public class UserAdapter extends RecyclerView.Adapter<UserAdapter.ViewHolder> {

    //사용자ID
    String id = "";

    //DB
    DBHelper dbHelper;

    //다이얼로그창
    AlertDialog.Builder builder;

    //사용자정보 담을 리스트
    ArrayList<UserVo> items = new ArrayList<UserVo>();

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
        View itemView = inflater.inflate(R.layout.user_item, viewGroup, false);

        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder viewHolder, int position) {

        //아이템 위치
        int mPosition = viewHolder.getAdapterPosition();

        UserVo item = items.get(mPosition);
        viewHolder.setItem(item);

        viewHolder.cardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Context context = v.getContext();

                //db객체 생성
                dbHelper = new DBHelper(context.getApplicationContext(), "USER_INFO.db", null, 1);

                //선택한 사용자 Id 담기
                id = items.get(mPosition).getId();

                //다이얼로그박스 호출
                builder = new AlertDialog.Builder(context);
                builder.setTitle("삭제");
                builder.setMessage("[" + id + "]해당 항목을 삭제하시겠습니까?");
                builder.setPositiveButton("예",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {

                                deleteItem(mPosition);
                                notifyDataSetChanged();
                                dbHelper.delete(id);
                            }
                        });
                builder.setNegativeButton("아니오",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.cancel();
                            }
                        });
                builder.show();
            }
        });
    }

    /**
     * 아이템 갯수 가져오기
     *
     * @return
     */
    @Override
    public int getItemCount() {
        return items.size();
    }


    /**
     * 아이템 등록
     *
     * @param alaramVo
     */
    public void addItem(UserVo alaramVo) {
        items.add(alaramVo);
    }

    public void deleteItem(int position) {

        items.remove(position);
    }

    /**
     * 아이템 전체삭제
     */
    public void removeAllItem() {
        items.clear();
    }

    class ViewHolder extends RecyclerView.ViewHolder {

        //초기화
        TextView tId;
        TextView tName;
        TextView tAge;
        CardView cardView;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);

            tId = itemView.findViewById(R.id.tId);      //아이디
            tName = itemView.findViewById(R.id.tName);  //이름
            tAge = itemView.findViewById(R.id.tAge);    //나이
            cardView = itemView.findViewById(R.id.cardView);
        }

        public void setItem(UserVo vo) {

            //텍스트에 데이터 담기
            tId.setText(vo.getId());
            tName.setText(vo.getName());
            tAge.setText(vo.getAge());
        }
    }
}
}

9. 데이터 담는그릇 만들기 (UserVo.java)

public class UserVo {

    private String id;
    private String name;
    private String age;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

 

 

 

간단한 기능을 하는 앱인데 생각보다 만들게 꽤 있네요.

메인화면(MainActivity), 등록화면(InsertFragment), 리스트화면(ListFragment)

, DB기능(DBHelper), 화면과데이터연결 기능(UserAdapter), 데이터담는그릇(UserVo)

 

직접 따라서 만들어 보시고 응용하시면 됩니다. 

딱 기본이시니 그리 어렵지는 않을꺼라고 생각이 듭니다. 

 

반응형

관련글 더보기

댓글 영역