Android

[Android] 리사이클러 뷰 (RecyclerView) + Vector Asset, 클래스 Intent: Serializable

eyoo 2022. 7. 14. 16:17

리스트 형식의 데이터를 보여줄때 RecyclerView를 사용한다.

RecyclerView에 넣어서 보여줄 하나의 행을 만들어야 한다.

이 행의 화면 개발을 위해 xml을 따로 만들어서 작업해야 한다.

이것을 위한 새로운 Layout Resource File을 만들자.

 

# 만들때 ConstraintLayout이 아닌 LinearLayout을 적용시킨다.

 

 

아래 구성으로 화면을 만들자.

 




그 후 TextView를 필요한 만큼 넣고 오른쪽 위에 닫기 버튼을 만들자.

Res를 우클릭하여 Vector Asset으로 닫기 아이콘을 만들수 있다.

 



Clip Art로 원하는 아이콘을 찾고 조정하여 만든다.

 



그러면 이제 res의 drawable에 만들어준 닫기 아이콘이 만들어진것을 확인할수있다.

 



이 아이콘을 사용해서 레이아웃을 만들었다.

 

# 전체 레이아웃의 height를 wrap_content한다.


이제 adapter 패키지를 하나 만들고 ContactAdapter 라는 클래스를 만들어 준다

 

# 어댑터는 떨어져있는 화면과 데이터를 연결시키는 역할을 한다.

 

이제 어댑터 클래스를 위에서 만든 xml파일 (contact.xml) 과 연결시킨다.

# row 화면에 맵핑할 어댑터 클래스 만드는 순서

 

 

1. 먼저 RecyclerView를 상속 하고 그 안에서 맨 밑에  ViewHolder 클래스를 만든다.

 

public class MemoAdapter extends RecyclerView {		// 여기
    public MemoAdapter(@NonNull Context context) {
        super(context);
    }

    public class ViewHolder extends RecyclerView.ViewHolder {		// 여기
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
        }
    }
}

# 생성자를 만들라는 경고 문구가 나오는데 처음 하나만 선택해서 만들어준다.

 

 

 

2. 연결하려는 row.xml의 기능들의 멤버변수 저장하고 itemView의 findViewById를 사용하여 연결시켜준다.

 

public class MemoAdapter extends RecyclerView {
    public MemoAdapter(@NonNull Context context) {
        super(context);
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView txtTitle;		// 여기
        TextView txtContent;
        ImageView imgDelete;
        CardView cardView;

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

            txtTitle = itemView.findViewById(R.id.txtTitle);		// 여기
            txtContent = itemView.findViewById(R.id.txtContent);
            imgDelete = itemView.findViewById(R.id.imgDelete);
            cardView = itemView.findViewById(R.id.cardView);

        }
    }
}

 # 여기가 엑티비티가 아닌 클래스인것에 유의하자.

 

 

3. 이제 어댑터 클래스의 멤버변수에 context와 쓰려고 했던 모델 클래스의 리스트를 저장하고 생성자를 만든다.

 

public class MemoAdapter extends RecyclerView {

    Context context;		// 여기
    List<Memo> memoList;

    public MemoAdapter(Context context, List<Memo> memoList ) {		// 여기
        this.context = context;
        this.memoList = memoList;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView txtTitle;
        TextView txtContent;
        ImageView imgDelete;
        CardView cardView;

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

            txtTitle = itemView.findViewById(R.id.txtTitle);
            txtContent = itemView.findViewById(R.id.txtContent);
            imgDelete = itemView.findViewById(R.id.imgDelete);
            cardView = itemView.findViewById(R.id.cardView);

        }
    }
}

# context는 메인 엑티비티를 나타내며 추가해준 리스트에서는 데이터를 넘겨준다.

# 어댑터에서의 context는 항상 관련 엑티비티를 나타낸다는것에 유의하자.

 

 

4. RecyclerView.Adapter의 데이터타입을 알려줘야 한다.

# 전 단계에서 만든 ViewHolder의 타입으로 설정 (extends RecyclerView.Adapter<어댑터클래스이름.ViewHolder>)

 

public class MemoAdapter extends RecyclerView.Adapter<MemoAdapter.ViewHolder> {		// 여기

    Context context;
    List<Memo> memoList;

    public MemoAdapter(Context context, List<Memo> memoList ) {
        this.context = context;
        this.memoList = memoList;
    }
    
    @NonNull		// 오버라이드 되어 생성됨
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return null;
    }

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

    }

    @Override
    public int getItemCount() {
        return 0;
    }    

    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView txtTitle;
        TextView txtContent;
        ImageView imgDelete;
        CardView cardView;

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

            txtTitle = itemView.findViewById(R.id.txtTitle);
            txtContent = itemView.findViewById(R.id.txtContent);
            imgDelete = itemView.findViewById(R.id.imgDelete);
            cardView = itemView.findViewById(R.id.cardView);

        }
    }
}

# 해당 코드가 빨간 밑줄이 쳐지는데 이를 클릭해서 implement methods를 모두 넣어주자.

 

 

 

5. 위에서 생성된 onCreateViewHolder와 onBindViewHolder 함수들을 현재 클래스의 ViewHolder라고 정의한다.

그 후 LayoutInflater와 holder를 사용하여 앞서 만들었던 row.xml을 연결시키고 행의 위치를 인식할수있도록 만든다.

마지막으로 getItemCount에서 리스트의 길이를 입력한다. 

 

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

    Context context;
    List<Memo> memoList;

    public MemoAdapter(Context context, List<Memo> memoList ) {
        this.context = context;
        this.memoList = memoList;
    }

    @NonNull
    @Override		// 여기
    public MemoAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.memo_row,parent,false);
        return new MemoAdapter.ViewHolder(view);
    }

    @Override		// 여기
    public void onBindViewHolder(@NonNull MemoAdapter.ViewHolder holder, int position) {
        Memo memo = memoList.get(position);
        
        holder.txtTitle.setText(memo.title);
        holder.txtContent.setText(memo.content);

    }

    @Override		// 여기
    public int getItemCount() {
        return memoList.size();
    }


    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView txtTitle;
        TextView txtContent;
        ImageView imgDelete;
        CardView cardView;

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

            txtTitle = itemView.findViewById(R.id.txtTitle);
            txtContent = itemView.findViewById(R.id.txtContent);
            imgDelete = itemView.findViewById(R.id.imgDelete);
            cardView = itemView.findViewById(R.id.cardView);

        }
    }
}

# onCreateViewHolder에서 row.xml을 연결하고 onBindViewHolder에서 해당 행의 위치를 연결시켜 데이터를 가져온다.

# 추가로 getItemCount에 size함수를 사용하여 리스트의 길이를 가져올수 있도록 작성한다.

 

 

더보기

 

연락처 앱에서 RecyclerView를 위한 어댑터를 만들었을때:

 

// row 화면에 맵핑할 어댑터 클래스 만드는 순서

// 1. RecyclerView.Adapter를 상속 받는다.

// 5. RecyclerView.Adapter의 데이터타입을 알려줘야 한다.
// 우리가 만든 ViewHolder의 타입으로 설정 (extends RecyclerView.Adapter<ContactAdapter.ViewHolder>) 빨갛게 될거임

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

    // 4. 어댑터 클래스의 멤버변수와 생성자를 만들어준다.
    Context context;
    List<Contact> contactList;

    public ContactAdapter(Context context, List<Contact> contactList) {
        this.context = context;
        this.contactList = contactList;
    }

    // 6. 아래 함수를 구현
    // RecyclerView.ViewHolder를 ContactAdapter.ViewHolder로
    // 6-1 findViewById를 실행할수있게끔 하는 함수
    @NonNull
    @Override
    public ContactAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view  = LayoutInflater.from(parent.getContext()).inflate(R.layout.contact_row,parent,false);
        return new ContactAdapter.ViewHolder(view);

    }

    // 6-2 메모리에 있는 데이터(리스트)를 화면에 표시하는 함수
    // RecyclerView.ViewHolder를 ContactAdapter.ViewHolder로
    @Override
    public void onBindViewHolder(@NonNull ContactAdapter.ViewHolder holder, int position) {
        Contact contact = contactList.get(position);

        holder.txtName.setText(contact.name);
        holder.txtPhone.setText(contact.phone);

    }

    @Override
    public int getItemCount() {
        return contactList.size();
    }


    // 2. 클래스 안에서 ViewHolder클래스를 만든다,
    // 이 클래스는 row.xml 화면에 있는 뷰를 연결시키는 클래스
    // 오류 표시 눌러서 생성자 만든다.
    // 화면과  연결할 자바 변수 만든다
    public class ViewHolder extends RecyclerView.ViewHolder{

        TextView txtName;
        TextView txtPhone;
        ImageView imgDelete;

        // 3. 생성자 안에 연결시키는 코드 작성
        public ViewHolder(@NonNull View itemView) {
            super(itemView);

            txtName = itemView.findViewById(R.id.txtName);
            txtPhone = itemView.findViewById(R.id.txtPhone);
            imgDelete = itemView.findViewById(R.id.imgDelete);

            imgDelete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // TODO : 엑스 이미지 누르면 해당 주소록 삭제 하도록 개발


                }
            });
        }
    }
}

 

 

이제 메인 엑티비티에서 멤버변수를 설정하고 onCreate에서 findViewById를 사용하여 recyclerView를 연결한다.

그 후 DB연결하고 데이터를 가져와서 보여준다.

 

// 멤버변수 설정
RecyclerView recyclerView;
ContactAdapter adapter;
ArrayList<Contact> contactList;

...

// onCrerate

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

        btnAddContact = findViewById(R.id.btnAddContact);
        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));

        // DB에서 주소록 데이터를 모두 가져와서 리사이클러뷰에 표시한다.
        DatabaseHandler db = new DatabaseHandler(MainActivity.this);

        contactList = db.getAllContact();

        adapter = new ContactAdapter(MainActivity.this,contactList);

        recyclerView.setAdapter(adapter);

 


그 후 앱을 실행시키면 아래와 같이 작동하는것을 볼수있다.

 



CardView로 모양을 예쁘게 만들자.

 

 

# cardCornerRadius와 cardElevation을 5dp씩 조정했다.



이제 행을 누르면 수정할수있도록 하자

 

수정하기 위해 먼저 원래 DB에 있던 데이터를 넘겨준다.

 

행을 눌러서 실행되기에 행의 화면정보를 가지고 있는 어댑터에서 Intent를 사용하여 EditActivity로 넘어갈수 있도록 한다. 

 

어댑터 클래스:

 

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

        // 유저가 몇번째 행을 클릭했는지 인덱스로 알려준다.
        int index = getAdapterPosition();

        // 이 인덱스에 저장되어있는 행을 가져온다.
        Contact contact = contactList.get(index);

        // TODO: 아이디 이름 전화번호를 수정하는 데이터를 넘겨준다.
        Intent intent = new Intent(context, EditActivity.class);
        
        intent.putExtra("id",contact.id);
        intent.putExtra("name",contact.name);
        intent.putExtra("phone",contact.phone);

        context.startActivity(intent);

    }
});

 

 

EditActivity:

 

    EditText editName;
    EditText editPhone;
    Button btnEdit;


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

        int id = getIntent().getIntExtra("id",0);
        String name = getIntent().getStringExtra("name");
        String phone = getIntent().getStringExtra("phone");

        editName = findViewById(R.id.editName);
        editPhone = findViewById(R.id.editPhone);
        btnEdit = findViewById(R.id.btnEdit);

        editName.setText(name);
        editPhone.setText(phone);

        btnEdit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String name = editName.getText().toString().trim();
                String phone = editPhone.getText().toString().trim();

                if(name.isEmpty() || phone.isEmpty()){
                    Toast.makeText(EditActivity.this, "수정할 정보를 확인해주세요", Toast.LENGTH_SHORT).show();
                }

                AlertDialog.Builder alert = new AlertDialog.Builder(EditActivity.this);
                alert.setTitle("수정하시겠습니까?");
                alert.setPositiveButton("예", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        DatabaseHandler db = new DatabaseHandler(EditActivity.this);

                        // 업데이트할때 필요한 파라미터는 Contact 클래스의 객체다
                        // 따라서 Contact 클래스의 객체를 만들어서 함수 호출한다.
                        Contact contact = new Contact(id,name,phone);
                        db.updateContact(contact);
                        Toast.makeText(EditActivity.this, "수정되었습니다", Toast.LENGTH_SHORT).show();
                        finish();
                    }
                });
                alert.setNegativeButton("아니요",null);
                alert.show();
            }
        });

 

 

컨택트 클래스 자체를 Intent 하여 수정후 메인으로 돌아왔을때 수정된 내용이 바로 보일수 있도록한다.

 

어댑터 클래스:

 

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

                    // 유저가 몇번째 행을 클릭했는지 인덱스로 알려준다.
                    int index = getAdapterPosition();

                    Log.i("MyContact","인덱스 확인 : "+index);

                    // 이 인덱스에 저장되어있는 행을 가져온다.
                    Contact contact = contactList.get(index);

                    Log.i("MyContact","인덱스에 해당되는 행 확인 : "+contact);

                    // TODO: 아이디 이름 전화번호를 수정하는 데이터를 넘겨준다.
                    Intent intent = new Intent(context, EditActivity.class);

                    // TODO: 수정하고 나면 화면에 반영
                    // 먼저 어댑터에서 에디트로 클래스 자체를 보낸다.
                    intent.putExtra("contact",contact);
                    // public class Contact implements Serializable  ,클래스에서 임플리먼트 적용


//                    intent.putExtra("id",contact.id);
//                    intent.putExtra("name",contact.name);
//                    intent.putExtra("phone",contact.phone);

                    context.startActivity(intent);

                }
            });

# 객체를 putExtra로 넘겨줄때는 해당클래스에 implement Serializable 해야 한다.

 

 

EditActivity:

 

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

        // TODO 컨택트를 겟 인텐트하고 캐스트까지 해야함
        Contact contact = (Contact) getIntent().getSerializableExtra("contact");

//        int id = getIntent().getIntExtra("id",0);
//        String name = getIntent().getStringExtra("name");
//        String phone = getIntent().getStringExtra("phone");

        editName = findViewById(R.id.editName);
        editPhone = findViewById(R.id.editPhone);
        btnEdit = findViewById(R.id.btnEdit);

        // contact를 가져왔으니 contact. 를 붙여준다
        editName.setText(contact.name);
        editPhone.setText(contact.phone);

        btnEdit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String name = editName.getText().toString().trim();
                String phone = editPhone.getText().toString().trim();

                if(name.isEmpty() || phone.isEmpty()){
                    Toast.makeText(EditActivity.this, "수정할 정보를 확인해주세요", Toast.LENGTH_SHORT).show();
                }

                AlertDialog.Builder alert = new AlertDialog.Builder(EditActivity.this);
                alert.setTitle("수정하시겠습니까?");
                alert.setPositiveButton("예", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        DatabaseHandler db = new DatabaseHandler(EditActivity.this);

//                        // 업데이트할때 필요한 파라미터는 Contact 클래스의 객체다
//                        // 따라서 Contact 클래스의 객체를 만들어서 함수 호출한다.
//                        Contact contact = new Contact(id,name,phone);

                        // TODO 위의 컨택트를 객체생성하는것이 아니라 컨택트의 이름과 폰에 가져온 정보를 넣어준다.
                        contact.name = name;
                        contact.phone = phone;

                        db.updateContact(contact);
                        Toast.makeText(EditActivity.this, "수정되었습니다", Toast.LENGTH_SHORT).show();
                        finish();
                    }
                });
                alert.setNegativeButton("아니요",null);
                alert.show();
            }
        });




    }
}

# getSerializableExtra로 받는쪽에서는 (Memo)로 해당 데이터가 어떤 객체인지를 알려준다.

 

 

그 후, 메인 의 onCreate에 작성했던 코드를 onResume에 올긴다.

 

@Override
protected void onResume() {
    super.onResume();
    printDBData();

    // DB에서 주소록 데이터를 모두 가져와서 리사이클러뷰에 표시한다.
    DatabaseHandler db = new DatabaseHandler(MainActivity.this);

    contactList = db.getAllContact();

    adapter = new ContactAdapter(MainActivity.this,contactList);

    recyclerView.setAdapter(adapter);
    db.close();
}

 

 

삭제기능도 X버튼(imgDelete)에 만들어 보자.

 

어댑터 클래스:

 

int deleteIndex;

...

imgDelete.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // TODO : 엑스 이미지 누르면 해당 주소록 삭제 하도록 개발

        // 알러트 다이얼로그 하기전에 먼저 행의 위치를 인덱스로 저장
        deleteIndex = getAdapterPosition();

        AlertDialog.Builder alert = new AlertDialog.Builder(context);
        alert.setTitle("삭제하시겠습니까?");
        alert.setPositiveButton("예", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {

                // DB 연결한다.
                DatabaseHandler db = new DatabaseHandler(context);

                // 유저가 몇번째 행을 클릭했는지 인덱스로 알려준다.
                Contact contact = contactList.get(deleteIndex);
                db.deleteContact(contact);
                db.close();

                //
                contactList.remove(deleteIndex);
                notifyDataSetChanged();

                Toast.makeText(context, "삭제되었습니다", Toast.LENGTH_SHORT).show();
            }
        });

        alert.setNegativeButton("아니요",null);
        alert.show();



    }
});

# 어댑터 클래스의 위쪽에서 멤버변수를 생성했다.  (int deleteIndex)

 

 

더보기

 

사용한 예:

# 메모장 앱

 

DatabaseHandler

 

public class DatabaseHandler extends SQLiteOpenHelper {
    public DatabaseHandler(@Nullable Context context) {
        super(context, Util.DATABASE_NAME,null, Util.DATABASE_VERSION );
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        // 테이블 생성
        String CREATE_MEMO_TABLE = "create table " + Util.TABLE_NAME + "("+
                Util.KEY_ID + " integer primary key, "+
                Util.KEY_TITLE + " text, "+
                Util.KEY_CONTENT + " text )";
        Log.i("MyMemo", "SQL 테이블 생성문 : "+CREATE_MEMO_TABLE);

        // SQL 테이블 생성문을 넣어서 실행
        sqLiteDatabase.execSQL(CREATE_MEMO_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        // 테이블을 삭제하고 다시 만든다,
        String DROP_TABLE = "drop table " + Util.TABLE_NAME;
        sqLiteDatabase.execSQL(DROP_TABLE, new String[]{Util.DATABASE_NAME});

        onCreate(sqLiteDatabase);
    }

    // 메모 생성함수
    public void addMemo(Memo memo){
        SQLiteDatabase db = this.getWritableDatabase();
        db.execSQL("insert into memo ( " + Util.KEY_TITLE + " , "+ Util.KEY_CONTENT + " ) values ( ? , ? )", new String[]{memo.title, memo.content} );
        db.close();

    }

    // 메모 하나 가져오는 함수
    public void getMemo(int id){
        SQLiteDatabase db = this.getReadableDatabase();

        db.execSQL("select * from memo where id = ?" ,new String[]{""+id});
        db.close();
    }

    // 모든 메모 가져오는 함수
    public ArrayList<Memo> getAllMemo() {
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.rawQuery("select * from memo", null);

        ArrayList<Memo> memoList = new ArrayList<Memo>();

        if(cursor.moveToFirst()){
            do{
                Memo memo = new Memo(cursor.getInt(0),cursor.getString(1), cursor.getString(2));
                memoList.add(memo);
            } while(cursor.moveToNext());
        }

        return memoList;
    }

    // 메모 수정하는 함수
    public void updateMemo(Memo memo){
        SQLiteDatabase db = this.getWritableDatabase();

        db.execSQL("update memo set title = ?, content = ? where id = ?",new String[]{memo.title, memo.content, memo.id+""});

        db.close();
    }

    public void updateMemo(int id, String title, String content){
        SQLiteDatabase db = this.getWritableDatabase();

        db.execSQL("update memo set title = ?, content = ? where id = ?",new String[]{title, content, id+""});

        db.close();
    }

    // 메모 삭제하는 함수
    public void deleteMemo (Memo memo){
        // delete from contact where id = 1
        SQLiteDatabase db = this.getWritableDatabase();
        db.execSQL("delete from memo where id = ?",new String[]{memo.id+""});
        db.close();
    }

    // 메모 검색하는 함수
    public ArrayList<Memo> searchMemo (String keyword){
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.rawQuery("select * from memo where title like '%"+keyword+"%' or content like '%"+keyword+"%'",null);

        ArrayList<Memo> memoList = new ArrayList<Memo>();

        if(cursor.moveToFirst()){
            do{
                Memo memo = new Memo(cursor.getInt(0),cursor.getString(1), cursor.getString(2));
                memoList.add(memo);
            } while(cursor.moveToNext());
        }

        return memoList;
    }


}

 

 

 메인 엑티비티

 

public class MainActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    MemoAdapter adapter;
    ArrayList<Memo> memoList;

    Button btnAdd;
    EditText editSearch;
    ImageView imgSearch;
    ImageView imgDelete;


    @Override
    protected void onResume() {
        super.onResume();
        printDBData();

        // 메모리스트에는 지금 데이터가 없다.
        // DB에 있으니 먼저 DB에 있는 메모리스트를 가져온다.

        DatabaseHandler db = new DatabaseHandler(MainActivity.this);
        memoList = db.getAllMemo();
        adapter = new MemoAdapter(MainActivity.this, memoList);
        recyclerView.setAdapter(adapter);
        db.close();

    }

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


        btnAdd = findViewById(R.id.btnAdd);
        editSearch = findViewById(R.id.editSearch);
        imgSearch = findViewById(R.id.imgSearch);
        imgDelete = findViewById(R.id.imgDelete);
        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));


        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Intent intent = new Intent(MainActivity.this, CreateActivity.class);
                startActivity(intent);

            }
        });

        imgSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String keyword = editSearch.getText().toString().trim();
                DatabaseHandler db = new DatabaseHandler(MainActivity.this);
                memoList = db.searchMemo(keyword);

                // 결과표시
                adapter = new MemoAdapter(MainActivity.this,memoList);
                recyclerView.setAdapter(adapter);

            }
        });

        imgDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                editSearch.setText("");
                DatabaseHandler db = new DatabaseHandler(MainActivity.this);
                memoList = db.getAllMemo();
                adapter = new MemoAdapter(MainActivity.this, memoList);
                recyclerView.setAdapter(adapter);
                db.close();


            }
        });
    }

    // 로그 찍는 함수
    void printDBData(){
        DatabaseHandler db = new DatabaseHandler(MainActivity.this);
        ArrayList<Memo> memoList =  db.getAllMemo();
        for(Memo data : memoList) {
            Log.i("MyContact", "id : " + data.id + " , title : " + data.title + " , content : " + data.content);
        }
    }
}

 

 

크리에이트 엑티비티

 

public class CreateActivity extends AppCompatActivity {

    EditText editTitle;
    EditText editContent;
    Button btnSave;

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

        editTitle = findViewById(R.id.editTitle);
        editContent = findViewById(R.id.editContent);
        btnSave = findViewById(R.id.btnUpdate);

        btnSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String title = editTitle.getText().toString().trim();
                String content = editContent.getText().toString().trim();

                if(title.isEmpty()){
                    Toast.makeText(CreateActivity.this,"메모를 작성해주세요",Toast.LENGTH_SHORT).show();
                    return;
                }

                DatabaseHandler db = new DatabaseHandler(CreateActivity.this);
                Memo memo = new Memo( title, content );
                db.addMemo(memo);

                Toast.makeText(CreateActivity.this,"메모가 저장되었습니다.",Toast.LENGTH_SHORT).show();
                finish();

            }
        });

    }
}

 

 

업데이트 엑티비티

 

public class UpdateActivity extends AppCompatActivity {

    EditText editTitle;
    EditText editContent;
    Button btnUpdate;

    Memo memo;

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

        memo = (Memo) getIntent().getSerializableExtra("memo");

        editTitle = findViewById(R.id.editTitle);
        editContent = findViewById(R.id.editContent);
        btnUpdate = findViewById(R.id.btnUpdate);

        editTitle.setText(memo.title);
        editContent.setText(memo.content);

        btnUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String title = editTitle.getText().toString().trim();
                String content = editContent.getText().toString().trim();

                memo.title = title;
                memo.content = content;

                DatabaseHandler db = new DatabaseHandler(UpdateActivity.this);
                db.updateMemo(memo);
                finish();

            }
        });

    }
}

 

 

어뎁터

 

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

    Context context;
    List<Memo> memoList;

    public MemoAdapter(Context context, List<Memo> memoList ) {
        this.context = context;
        this.memoList = memoList;
    }

    @NonNull
    @Override
    public MemoAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.memo_row,parent,false);
        return new MemoAdapter.ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MemoAdapter.ViewHolder holder, int position) {
        Memo memo = memoList.get(position);

        holder.txtTitle.setText(memo.title);
        holder.txtContent.setText(memo.content);

    }

    @Override
    public int getItemCount() {
        return memoList.size();
    }


    public class ViewHolder extends RecyclerView.ViewHolder {

        TextView txtTitle;
        TextView txtContent;
        ImageView imgDelete;
        CardView cardView;

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

            txtTitle = itemView.findViewById(R.id.txtTitle);
            txtContent = itemView.findViewById(R.id.txtContent);
            imgDelete = itemView.findViewById(R.id.imgDelete);
            cardView = itemView.findViewById(R.id.cardView);

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


                    int index = getAdapterPosition();
                    Memo memo = memoList.get(index);
                    Intent intent = new Intent(context, UpdateActivity.class);
                    intent.putExtra("memo",memo);

                    context.startActivity(intent);


                }
            });

            imgDelete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // TODO: 삭제버튼 기능
                    AlertDialog.Builder alert = new AlertDialog.Builder(context);
                    alert.setTitle("메모 삭제");
                    alert.setMessage("정말 삭제하시겠습니까?");
                    alert.setPositiveButton("네", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {

                            int index = getAdapterPosition();
                            Memo memo = memoList.get(index);

                            DatabaseHandler db = new DatabaseHandler(context);
                            db.deleteMemo(memo);

                            memoList.remove(index);
                            notifyDataSetChanged();

                        }
                    });
                    alert.setNegativeButton("아니요",null);
                    alert.show();

                }
            });



        }
    }
}