DB 서치
recyclerView 처리
AlertDialog
Serializable (객체를 인텐트로 전달하고자 할때사용하는것)
디자인 속성에
maxline 2 ( 2줄로 보여줘)
ellipsize end ( 줄을 초과하면 ...으로 표시)
cardConerRadius (라운딩)
cardElevaion (입체감주기)
main 액티비티
package com.leopard4.memorecycleapp;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import com.leopard4.memorecycleapp.adapter.MemoAdapter;
import com.leopard4.memorecycleapp.data.DatabaseHandler;
import com.leopard4.memorecycleapp.model.Memo;
import java.util.List;
public class MainActivity extends AppCompatActivity {
Button btnAdd;
EditText editSearch;
ImageView imgSearch, imgDelete;
RecyclerView recyclerView;
MemoAdapter adapter;
List<Memo> memoList;
@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(this));
// 버튼을 누르면 메모 생성화면으로 이동
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, AddActivity.class);
startActivity(intent);
}
});
// 검색기능
imgSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 검색어를 가져와서, DB에서 검색
String search = editSearch.getText().toString().trim();
// search가 비어있거나, 공백이면 이런코드도 작성할 수 있으나 여기선 필요없다.
// if(search.isEmpty() || search.equals("")){
// return;
// }
DatabaseHandler db = new DatabaseHandler(MainActivity.this);
memoList = db.searchMemo(search);
// 리사이클러뷰에 어댑터를 연결(화면에 표시)
adapter = new MemoAdapter(MainActivity.this, memoList);
recyclerView.setAdapter(adapter);
// 검색이 끝나면 검색어를 지운다.
editSearch.setText("");
}
});
// X이미지를 눌르면 메인화면으로 돌아간다.
imgDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// DB에서 데이터를 가져와서, 리사이클러뷰에 뿌려준다.
DatabaseHandler db = new DatabaseHandler(MainActivity.this);
memoList = db.getAllMemo();
// 리사이클러뷰에 어댑터를 연결
adapter = new MemoAdapter(MainActivity.this, memoList);
recyclerView.setAdapter(adapter);
}
});
}
@Override
protected void onResume() {
// DB에서 데이터를 가져와서, 리사이클러뷰에 뿌려준다.
DatabaseHandler db = new DatabaseHandler(MainActivity.this);
memoList = db.getAllMemo();
// 리사이클러뷰에 어댑터를 연결
adapter = new MemoAdapter(MainActivity.this, memoList);
recyclerView.setAdapter(adapter);
super.onResume();
}
}
db핸들러
package com.leopard4.memorecycleapp.data;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import androidx.annotation.Nullable;
import com.leopard4.memorecycleapp.model.Memo;
import com.leopard4.memorecycleapp.util.Util;
import java.util.ArrayList;
import java.util.List;
public class DatabaseHandler extends SQLiteOpenHelper {
public DatabaseHandler(@Nullable Context context) {
super(context, Util.DB_NAME, null, Util.DB_VERSION);
}
// 테이블 생성
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String CREATE_MEMO_TABLE = "create table memo ( id integer primary key, title text, content text)";
sqLiteDatabase.execSQL(CREATE_MEMO_TABLE); // SQL문 실행
}
// 기존에 테이블을 삭제하고, 새 테이블을 다시 만든다.
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
String DROP_TABLE = "drop table memo";
sqLiteDatabase.execSQL(DROP_TABLE, new String[]{Util.TABLE_NAME});
onCreate(sqLiteDatabase);
}
// 이제부터는 우리가 앱 동작시키는데 필요한
// CRUD 관련된 SQL문이 들어간,
// 메소드를 만들면 된다.
// 1. 메모 추가하는 메소드(함수) c (create)
public void addMemo(Memo memo) {
// 데이터베이스에 쓰기 위한 객체를 생성
SQLiteDatabase db = this.getWritableDatabase();
// 쿼리문작성
String query = "insert into memo (title, content) values ( ? , ?)";
String[] args = new String[] {memo.getTitle(), memo.getContent()};
// 데이터베이스에 저장
db.execSQL(query, args);
db.close();
}
// 2. 메모 읽어오는 메소드(함수) r (read)
public List<Memo> getAllMemo() {
// 데이터베이스 읽기 위한 객체 생성
SQLiteDatabase db = this.getReadableDatabase();
// 데이터베이스에서 데이터를 읽어오는 SQL문
String query = "select * from memo order by id desc";
// SQL문 실행
Cursor cursor = db.rawQuery(query, null);
// 데이터베이스에서 읽어온 데이터를
// Memo 객체에 저장
List<Memo> memoList = new ArrayList<>();
if (cursor.moveToFirst()) {
do {
int id = cursor.getInt(0); // 컬럼의 인덱스
String title = cursor.getString(1);
String content = cursor.getString(2);
Log.i("MEMO_TABLE", "id: " + id + ", title: " + title + ", content: " + content);
// 이 데이터를, 화면에 표시하기 위해서는
// 메모리에 전부 다 남아있어야 한다!!!
// 그래서, 이 데이터를, Memo 객체로 만들어서
Memo memo = new Memo(id, title, content);
// 이 Contact 객체를, List에 담아둔다.
memoList.add(memo); // 이미 order by로 역순으로 받아서 0 생략
} while (cursor.moveToNext());
}
db.close();
return memoList;
}
// 3. 메모 수정하는 메소드(함수) u (update)
public void updateMemo(Memo memo) {
SQLiteDatabase db = this.getWritableDatabase();
String query = "update memo " +
"set title = ?, content = ? " +
"where id = ? ";
db.execSQL(query, new String[]{memo.title, memo.content, memo.id + ""}); // flask의 record와 비슷하다.
db.close();
}
// 4. 메모 삭제하는 메소드(함수) d (delete)
public void deleteMemo(Memo memo) {
SQLiteDatabase db = this.getWritableDatabase();
String query = "delete from memo where id = ?";
String[] args = new String[]{memo.id + ""}; // 파라미터로 넘겨줄 값들을 배열로 만든다.
db.execSQL(query, args);
db.close();
}
// 검색기능
List<Memo> memoList = new ArrayList<>();
public List<Memo> searchMemo(String search) {
// 데이터 베이스에서 saerch를 찾아서 리턴해주는 메소드
SQLiteDatabase db = this.getReadableDatabase();
String query = "select * from memo where title like ? or content like ? order by id desc";
String[] args = new String[]{"%" + search + "%", "%" + search + "%"};
Log.i("searchLog", search + " " + args[0] + " " + args[1]);
Cursor cursor = db.rawQuery(query, args);
// 데이터베이스에서 읽어온 데이터를
// Memo 객체에 저장
if (cursor.moveToFirst()) { // 커서가 첫번째 행으로 이동
do {
int id = cursor.getInt(0); // 컬럼의 인덱스
String title = cursor.getString(1);
String content = cursor.getString(2);
Log.i("MEMO_TABLE", "id: " + id + ", title: " + title + ", content: " + content);
// 이 데이터를, 화면에 표시하기 위해서는
// 메모리에 전부 다 남아있어야 한다!!!
// 그래서, 이 데이터를, Memo 객체로 만들어서
Memo memo = new Memo(id, title, content);
// 이 Memo 객체를, List에 담아둔다.
memoList.add(memo); // 이미 order by로 역순으로 받아서 0 생략
} while (cursor.moveToNext());
}
db.close();
return memoList;
}
}
memo 클래스
package com.leopard4.memorecycleapp.model;
import java.io.Serializable;
public class Memo implements Serializable {
public int id;
public String title;
public String content;
public Memo() {
}
public Memo(String title, String content) {
this.title = title;
this.content = content;
}
public Memo(int id, String title, String content) {
this.id = id;
this.title = title;
this.content = content;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
memo 어댑터
package com.leopard4.memorecycleapp.adapter;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import com.leopard4.memorecycleapp.EditActivity;
import com.leopard4.memorecycleapp.R;
import com.leopard4.memorecycleapp.data.DatabaseHandler;
import com.leopard4.memorecycleapp.model.Memo;
import java.util.List;
public class MemoAdapter extends RecyclerView.Adapter<MemoAdapter.viewHolder>{
Context context;
List<Memo> memoList;
int deleteIndex;
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, EditActivity.class);
intent.putExtra("memo", memo);
context.startActivity(intent);
}
});
// 삭제버튼을 누르면 alertdialog를 띄워서 삭제할지 물어본다.
imgDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 0) 어느 주소록을 삭제할것인지
// 삭제할 주소록을 가져온다 (어떤 행을 눌렀는지 파악한다.)
deleteIndex = getAdapterPosition();
// 1) 알러트 다이얼로그 나온다.
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("삭제");
builder.setMessage("정말 삭제하시겠습니까?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 2) 알러트 다이얼로그에서 Yes 눌렀을때
// 데이터베이스에서 삭제
DatabaseHandler db = new DatabaseHandler(context);
Memo memo = memoList.get(deleteIndex);
db.deleteMemo(memo);
// 알러트 다이얼로그는 액티비티가 아니므로
// 메인액티비티의 onResume 함수가 실행안된다.
// 따라서 화면 갱신이 안된다.
// 즉, 디비에 저장된 데이터 삭제했으니,
// 메모리에 저장된 데이터도 삭제한다.
memoList.remove(deleteIndex);
// 데이터가 변경되었으니, 화면 갱신하라고 어댑터의 함수호출 (상속받은기능)
notifyDataSetChanged();
}
});
// 3) 알러트 다이얼로그에서 No 눌렀을때
// 아무것도 안한다.
builder.setNegativeButton("No", null);
builder.show();
}
});
}
}
}
edit 액티비티
package com.leopard4.memorecycleapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.leopard4.memorecycleapp.data.DatabaseHandler;
import com.leopard4.memorecycleapp.model.Memo;
public class EditActivity extends AppCompatActivity {
EditText editTitle;
EditText editContent;
Button btnSave;
int id;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit);
editTitle = findViewById(R.id.editTitle);
editContent = findViewById(R.id.editContent);
btnSave = findViewById(R.id.btnSave);
Memo memo = (Memo) getIntent().getSerializableExtra("memo");
id = memo.getId();
editTitle.setText(memo.getTitle());
editContent.setText(memo.getContent());
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() || content.isEmpty()) {
Toast.makeText(EditActivity.this, "모두입력하세요", Toast.LENGTH_SHORT).show();
return;
}
Memo memo = new Memo(id, title, content);
// DB에 저장한다.
DatabaseHandler db = new DatabaseHandler(EditActivity.this);
db.updateMemo(memo);
// 유저한테 잘 저장되었다고, 알려주고
Toast.makeText(EditActivity.this, "수정되었습니다", Toast.LENGTH_SHORT).show();
// 액티비티 종료, 메인 액티비티로 돌아간다.(메인액티비티는 뒤에 숨어있었으므로)
finish();
}
});
}
}
add 액티비티
package com.leopard4.memorecycleapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.leopard4.memorecycleapp.data.DatabaseHandler;
import com.leopard4.memorecycleapp.model.Memo;
public class AddActivity extends AppCompatActivity {
EditText editTitle;
EditText editContent;
Button btnSave;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add);
editTitle = findViewById(R.id.editTitle);
editContent = findViewById(R.id.editContent);
btnSave = findViewById(R.id.btnSave);
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() || content.isEmpty()) {
Toast.makeText(AddActivity.this, "제목과 내용을 모두 입력해주세요", Toast.LENGTH_SHORT).show();
return;
}
// 묶어서 처리할 Memo 클래스를 하나 만든다.
Memo memo = new Memo(title, content);
// DB에 저장한다. // 힙에있는건 날라가므로
DatabaseHandler db = new DatabaseHandler(AddActivity.this);
db.addMemo(memo);
// 유저한테 잘 저장되었다고, 알려주고
Toast.makeText(AddActivity.this, "저장되었습니다", Toast.LENGTH_SHORT).show();
// 액티비티 종료
finish();
}
});
}
}
util
package com.leopard4.memorecycleapp.util;
public class Util {
public static final int DB_VERSION = 1;
public static final String DB_NAME = "memo_db";
public static final String TABLE_NAME = "memo";
// 테이블의 컬럼 관련 상수들
public static final String KEY_ID = "id";
public static final String KEY_TITLE = "title";
public static final String KEY_CONTENT = "content";
}
0
메인액티비티에 아래코드를 추가하면 된다.
editSearch.addTextChangedListener(new TextWatcher() {
//
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
//
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
// 유저가 입력한 키워드 뽑아서
String search = editSearch.getText().toString().trim();
// 2글자 이상 입력했을때만, 검색이 되도록 한다.
if(search.length() < 2 && search.length() > 0){
return;
}
// 디비에서 가져온후
DatabaseHandler db = new DatabaseHandler(MainActivity.this);
memoList = db.searchMemo(search);
// 화면에 표시
adapter = new MemoAdapter(MainActivity.this, memoList);
recyclerView.setAdapter(adapter);
}
});
android 스튜디오에서 레파지토리에 올리는방법
'Android' 카테고리의 다른 글
Android [회사직원관리앱] 양방향통신 launcher가 안될때/ 액션바 메뉴/ fab / 네트워크 프로그래스바 (0) | 2023.02.06 |
---|---|
Android 네트워크 통신 (0) | 2023.02.03 |
Android [주소록앱 1차 수정본] recycleView의 Adatpter에서, 새로운 activity를 실행하는 방법 / recycleView에서, 몇번째 행을 눌렀는지 알수있는 Adatpter의 함수(a.getAdapterPostion()) / 다른 activity로 데이터 전.. (0) | 2023.02.01 |
Android [메모앱] recyclerView (0) | 2023.02.01 |
Android recyclerView, adapter (2) | 2023.02.01 |