728x90
반응형
바로가기 버튼을 누르면 해당url로 이동, 추가하기 누르면 url추가하는 앱 만들기
에뮬레이터 재실행했을때 데이터 안날라가게 하는 방법
1. 핸드폰 내장 DataVase에 저장하기 -> SQLite -> App삭제시 사라짐
2. 서버( JSP/Servlet, DAO )를 통해 Database에 저장하기 -> Volley ( 라이브러리 ) -> 인터넷 연결 필요
3. 실시간으로 데이터 주고받기 -> Google FireBase Realtime DataBase
DataBase에 연결할 class 하나 생성 - DBManager.java
ListView 항목에 클릭리스너 달아줄때 ( setOnitemClickListener 할때 )
Cutom을 했을 경우 클릭리스너가 동작하지 않는다
-> ListView의 옵션과 항목뷰의 옵션을 수정해야함
1. ListView의 옵션 중 clickable 속성을 true로 변경 ( main.xml)
2. 항목 뷰를 전부 선택해서 focusable, focusbleInTouchMode를 false로
●MainActivity
public class MainActivity extends AppCompatActivity {
ArrayList<directVO> data = new ArrayList<>();
ListView lv;
Button btn_add;
final int ADD = 1;
DBManager manager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager = new DBManager(getApplicationContext()); // DB 파일생성,테이블생성,connection 알아서 해줌
lv = findViewById(R.id.listview);
btn_add = findViewById(R.id.btn_add);
data.add(new directVO("네이버","https://www.naver.com"));
data.add(new directVO("다음","https://www.daum.net"));
data.add(new directVO("Youtube","https://www.youtube.com"));
data.add(new directVO("스마트인재개발원","https://www.smhrd.or.kr"));
DirectAdapter adapter = new DirectAdapter(getApplicationContext(),R.layout.directlist, data);
lv.setAdapter(adapter);
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, AddActivity.class);
startActivityForResult(intent, ADD);
}
});
Cursor cursor = manager.getAllData();
// Cursor 란 JDBC 에서 ResultSet과 같은 역할
// 데이터(행) 을 가리키고 있는 화살표
while(cursor.moveToNext()){
// 커서를 아래칸으로 옮기는동안 데이터있으면 true, 없으면 false
// 데이터가 존재하는 동안 반복하기 위해 while 문 사용
// 해당 행의 데이터 가져와서 arrayList 에 축적하기
String title = cursor.getString(0);
String address = cursor.getString(1);
data.add(new directVO(title, address));
}
adapter.notifyDataSetChanged();
// 리스트뷰 항목을 터치했을 때 해당항목 지워버리기
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// 이전 예제에서는 position (위치)로 해당 데이터를 지웠음 (ArrayList 에서)
// DB에 index 를 부여할 순 있지만 position(매개변수) 과 index(DB) 가 맞지 않을 수 있음
// title 로 지워야함
// -> 지금 클릭한 항목의 title 을 알아야함 凸
// 1. ArrayList의 position번째 값을 꺼내는 방법
// 2. 클릭이 이러난 항목의 textview에서 getText하는 방법
// DB에서 지우기
TextView tv_address = view.findViewById(R.id.tv_title);
manager.delete(tv_address.getText().toString());
// 눈에 뵈는 ListView에서도 지워야함
data.remove(position);
adapter.notifyDataSetChanged();
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == ADD){
if (resultCode == RESULT_OK){
String title = data.getStringExtra("title");
String address = data.getStringExtra("address");
this.data.add(new directVO(title,address));
// manager 클래스의 insert 메소드 호출
manager.insert(title,address);
}
}
}
}
●AddActivity
public class AddActivity extends AppCompatActivity {
EditText edt_title, edt_edt_address;
Button btn_ok;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add);
edt_title = findViewById(R.id.edt_title);
edt_edt_address = findViewById(R.id.edt_address);
btn_ok = findViewById(R.id.btn_ok);
btn_ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String title = edt_title.getText().toString();
String address = edt_edt_address.getText().toString();
Intent intent = new Intent();
intent.putExtra("title",title);
intent.putExtra("address",address);
setResult(RESULT_OK, intent);
finish();
}
});
}
}
●DBManager
public class DBManager extends SQLiteOpenHelper {
public DBManager(@Nullable Context context) {
super(context, "Direct.db", null, 1);
// 1. context -> 화면(Activity)정보
// 2. name -> DataBase 파일이름
// 3. factory -> JDBC의 ResultSet 과 같은 일을 하는 객체
// 4. version -> DB의 버전 , 최초 만들때는 1
// 자식클래스의 생성자에 매개변수가 너무 많다 -> 적당히 지우기 ( Context 만 남기고 다 지우기)
}
// 부모 클래스에 매개변수가 잇는 생성자가 있다면
// 자식 클래스에서 반드시 부모클래스의 생성자를 호출해 주어야한다
// super -> 자식 클래스의 생성자에서만 호출가능
@Override
public void onCreate(SQLiteDatabase db) {
// 데이터베이스 파일이 최초로 생성될 때 호출
// 1.테이블 생성하는 소스코드 입력하기
String sql = "create table direct(title text, address text)";
// text(문자열)타입의 컬럼 2개생성
// 2. sql 문장 전송하기( 매개변수로 주어진 SQLite DateBase 객체 사용 )
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 데이터베이스 파일의 버전이 바뀌었을때
// 버전이 바뀌면 Table 지우고 다시 만드는 소스코드 입력
String sql = "drop table direct";
db.execSQL(sql); //테이블 지우기
onCreate(db); //다시생성
}
public void insert(String title, String address) {
// 리펙토링 -> 에러를 해결해나가는 방식으로 개발
// 1. 쓸 수 있는 데이터베이스 객체 꺼내기
SQLiteDatabase db = this.getWritableDatabase();
// 2. 데이터를 insert -> Key, value 형태로 insert
ContentValues cv = new ContentValues();
cv.put("title",title); //컬럼명과 데이터를 매개변수로 넣어준다
cv.put("address",address);
db.insert("direct",null,cv);
}
public Cursor getAllData() {
// 1. DataBase 객체 꺼내기
SQLiteDatabase db = this.getReadableDatabase();
// 2. select 쿼리문 날리기
String sql = "select * from direct";
Cursor cs = db.rawQuery(sql, null);
return cs;
}
public void delete(String text) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete("direct", "title='"+text+"'", null);//바로 변수에 넣었기 때문에 null
}
}
●DirectVO
public class directVO {
private String title;
private String address;
public directVO(String title, String address) {
this.title = title;
this.address = address;
}
public String getTitle() {
return title;
}
public String getAddress() {
return address;
}
}
●DirectAdapter
public class DirectAdapter extends BaseAdapter {
private Context c;
private int layout;
private ArrayList<directVO> data;
private LayoutInflater inflater;
public DirectAdapter(Context c, int layout, ArrayList<directVO> data) {
this.c = c;
this.layout = layout;
this.data = data;
this.inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null){
convertView = inflater.inflate(layout, parent, false);
// 최초 convertView 가 inflate 될때 ( 첫 항목이 만들어질때)
holder = new ViewHolder(); // 새 Holder를 만든다
holder.tv_title = convertView.findViewById(R.id.tv_title); //Holder 에 TextView , Button 저장
holder.tv_address = convertView.findViewById(R.id.tv_address);
holder.btn_go = convertView.findViewById(R.id.btn_go);
convertView.setTag(holder); // 완성된 Holder를 convertView에 부착
}else { //최초 한번이 아닐때
holder = (ViewHolder)convertView.getTag();
}
// getView는 항목하나가 만들어 질 때마다 호출이 되는데
// 항목을 만들 때 마다 findViewById 를 하면 굉장히 부하가 걸림
// ViewHolder 패턴을 이용하여 효율적으로 View 들을 관리하기
// ViewHolder - View 를 저장해둔 객체(VO랑 비슷)
holder.tv_title.setText(data.get(position).getTitle());
holder.tv_address.setText(data.get(position).getAddress());
holder.btn_go.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 버튼 눌렀을때 address로 바로가기
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(data.get(position).getAddress()));
// Activity 클래스가 아니라서 (AppCompatActivity 클래스를 상속하지 않아서)
// 바로 startActivity 메소드 사용x , 생성자를 통해서 전달받은 Context의 도움을 받아 실행
// startActivity를 수행하면 task에 process 가 쌓이는데
// 이곳은 Activity가 아니라 task에 접근 x
// 그래서 intent에 옵션 (flag)을 설정하여 새로운 task를 생성
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
c.startActivity(intent);
}
});
return convertView;
}
// ViewHolder 설계
public class ViewHolder{
TextView tv_title;
TextView tv_address;
Button btn_go;
}
}
반응형
'Android' 카테고리의 다른 글
로그인 후 채팅 방 만들기?? (0) | 2021.04.06 |
---|---|
서버 통신 로그인 DB연동( Volley 라이브러리 ) (0) | 2021.04.03 |
Adapter -> Custom ListView활용 (0) | 2021.03.25 |
Adapter View (0) | 2021.03.24 |
Intent 사용 2 (0) | 2021.03.23 |