Android 4대 컴포넌트
1.activity: 화면을 구성하는 단위
2. service: activity와 비슷하지만 사용자에게 보여지는 화면이 없는 종료되어있는 상태에서도 동작은 구성요소(백그라운드)
3.BroadCastReceiver: 핸드폰(하드웨어)에서 일어나는 모든 일을 감지
4. Content Provider: App 끼리 데이터를 제공할 수 있음 (대신 공개된 정보만)
Intent: 4대 구성요소 중간다리역할을 하는 메세지 객체
1) 묵시적(암묵적) 인텐트
액션(VIEW,WEB_SEARCH,..CALL DIAL)
액션+데이터
액션 (카메라, 웹서치, 문자메세지)
2) 명시적 인텐트
- 구성요소들끼리 데이터를 주고받거나, 이동할 때 사용하는 인텐트
1) startActivity(인텐트) ---> 단방향
데이터를 주거나 or 받는다
2) startActivityForResult(인텐트, requestCode) --> 양방향
데이터를 주고, 받는다
1.MainActivity에서 버튼을 누르면 Sub한테 이동(요청)
StartActivityForResult(인텐트, requestCode)
2. Sub에 버튼을 눌렀을 때 EditText에 담겨있고 값을 들고 Main으로 온다~!
3. Main에서 값을 받아줘야 한다( OnActivityResult()오버라이딩 -> intent에서 데이터를 꺼내주는 메서드)
[BoardActivity]
package com.example.ex20221129
import android.content.DialogInterface
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.View.OnClickListener
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.EditText
import android.widget.ListView
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresPermission.Write
import androidx.appcompat.app.AlertDialog
class BoardActivity : AppCompatActivity() {
lateinit var btnWrite: Button
lateinit var tvContent: TextView
lateinit var btnLogin1: Button
lateinit var btnBoard : Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_board)
tvContent = findViewById(R.id.tvContent)
btnWrite = findViewById(R.id.btnWrite)
btnLogin1 = findViewById(R.id.btnLogin1)
var lv = findViewById<ListView>(R.id.lv)
val etBoard = findViewById<EditText>(R.id.etBoard)
btnBoard = findViewById<Button>(R.id.btnBoard)
btnBoard.isEnabled = false
btnLogin1.setOnClickListener {
val intent = Intent(this@BoardActivity,
LoginActivity::class.java)
// 양방향 통신
result.launch(intent)
}
lv.setOnItemClickListener { adapterView, view, i, l ->
// adapterView : ListView에 대한 정보 받아옴
// view : ListView가 있는 현재 페이지에 대한 정보를 받아옴
// i (position) -> 내가 클릭한 item위치 (index 0~)
// l (id) : Long -> 내가 클릭한 item의 고유한 값
Toast.makeText(this,
adapterView.adapter.getItem(i).toString(),
Toast.LENGTH_SHORT).show()
}
// onCreate() 안쪽에
// Adapter View를 사용하기 위한 6단계
// 1. Container 결정
// -> ListView의 위치를 결정!
// 2. Template 결정
// -> 각 항목(Item)에 적용될 디자인을 결정!
// -> Layout 패키지에 xml 형태로 생성!!
// board_list.xml 최상위 레이아웃 : TextView
// 이 때, id는 tvBoard
// 3. Item 결정
val data = ArrayList<String>()
data.add("1. 오늘은 점심이 배불렀다")
data.add("2. 비싼 음료 시켰는데 맛이 맹맹하다")
data.add("3. 돈 안내고 먹어서 다행이다")
// 4. Adapter 결정
// Adapter : 디자인(항목 뷰, 템플릿) + Item 결합해서
// AdapterView에 동적으로 뿌려주는 역할!
// ArrayAdapter를 사용하자
// 조건) 템플릿이 TextView, Item 요소가 String
// 생성자의 요소 4개
// 1) 페이지 정보
// 2) 템플릿(항목 뷰)
// 3) TextView의 id
// 4) Item
val adapter = ArrayAdapter<String>(this, R.layout.board_list, R.id.tvBoard, data)
// 5. Container에 Adapter 부착
lv.adapter = adapter
// 6. Event 처리
// 1) btnBoard를 클릭했을 때,
btnBoard.setOnClickListener {
// 2) etBoard의 값을 가져와서
// 3) val input에 저장
val input: String = etBoard.text.toString()
// 4) data에 input을 추가!
data.add(input)
// adapter를 새로고침하자!
adapter.notifyDataSetChanged()
etBoard.text = null
}
lv.setOnItemClickListener { adapterView, view, i, l ->
// AlertDialog 옵션 정보를 담는 builder 생성!
val builder = AlertDialog.Builder(this)
builder.setTitle("게시글 삭제")
builder.setMessage("정말 삭제하시겠습니까?")
builder.setPositiveButton("삭제",
DialogInterface.OnClickListener{p0, p1 ->
data.removeAt(i)
adapter.notifyDataSetChanged()
})
builder.setNegativeButton("취소", null)
// 주의
// builder를 통해 옵션을 단 이후
// 맨 마지막에는 무조건! show() 함수를 달아야 한다
builder.show()
}
// AdapterView 만드는 법
// 1. Container 결정 -> ListView의 위치 결정
// 2. Template 결정 -> 항목 뷰 디자인
// 3. Item 결정 -> ArrayList<String>
// 4. Adapter 결정 -> ArrayAdapter
// 5. Container에 Adapter 부착
// 6. Event 처리리
// 4) data에 input을 추가!
}
// intent 받아주는 콜백함수 생성
val result = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
if(it.resultCode == RESULT_OK) {
btnWrite.isEnabled = true
btnBoard.isEnabled = true
// tvContent에 로그인 성공
tvContent.text = "로그인 성공"
}else if(it.resultCode == RESULT_CANCELED){
// tvContent에 로그인 실패
tvContent.text="로그인 실패"
}
}
}
[activity_board.xml]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".BoardActivity">
<Button
android:id="@+id/btnWrite"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:enabled="false"
android:text="글작성"
app:layout_constraintBottom_toBottomOf="@+id/tvContent"
app:layout_constraintEnd_toStartOf="@+id/btnLogin1"
app:layout_constraintTop_toTopOf="@+id/tvContent" />
<TextView
android:id="@+id/tvContent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="글 작성은 로그인 후 가능"
android:textSize="16sp"
app:layout_constraintEnd_toStartOf="@+id/btnWrite"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnLogin1"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:text="로그인"
app:layout_constraintBottom_toBottomOf="@+id/btnWrite"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/btnWrite" />
<TextView
android:id="@+id/textView2"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="#3F51B5"
android:gravity="center"
android:text="게시판"
android:textColor="#FFFFFF"
android:textSize="34sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnWrite" />
<ListView
android:id="@+id/lv"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/etBoard"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
<EditText
android:id="@+id/etBoard"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btnBoard"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btnBoard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="글쓰기"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
[LoginActivity]
package com.example.ex20221129
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
class LoginActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
val btnLogin = findViewById<Button>(R.id.btnLogin)
val etId = findViewById<EditText>(R.id.etId)
val etPw = findViewById<EditText>(R.id.etPw)
btnLogin.setOnClickListener {
var loginId = etId.text.toString()
var loginPw = etPw.text.toString()
val intent = Intent()
if(loginId == "hyewon" && loginPw == "1234") {
intent.putExtra("loginId", loginId)
intent.putExtra("loginPw", loginPw)
setResult(RESULT_OK, intent)
}else {
setResult(RESULT_CANCELED, intent)
}
finish()
}
}
}
[activity.login.xml]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".LoginActivity">
<EditText
android:id="@+id/etId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="200dp"
android:ems="10"
android:hint="ID를 입력해주세요"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/etPw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:ems="10"
android:hint="PW를 입력해주세요"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="@+id/etId"
app:layout_constraintStart_toStartOf="@+id/etId"
app:layout_constraintTop_toBottomOf="@+id/etId" />
<Button
android:id="@+id/btnLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="LOGIN"
app:layout_constraintEnd_toEndOf="@+id/etPw"
app:layout_constraintStart_toStartOf="@+id/etPw"
app:layout_constraintTop_toBottomOf="@+id/etPw" />
</androidx.constraintlayout.widget.ConstraintLayout>
[LunchActivity]
package com.example.ex20221129
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.EditText
import android.widget.ListView
import android.widget.TextView
import java.util.Random
class LunchActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_lunch)
// Adapter View 만드는 6단계
// 1. Container 결정 (위치 결정)
val lvLunch = findViewById<ListView>(R.id.lvLunch)
val etAdd = findViewById<EditText>(R.id.etAdd)
val btnAdd = findViewById<Button>(R.id.btnAdd)
val btnResult = findViewById<Button>(R.id.btnResult)
val tvLunch = findViewById<TextView>(R.id.tvLunch)
// viewBinding 기법 -> 초기화를 해결
// 2. Template 결정 (아이템 디자인)
// lunch_list.xml
// 3. Item 결정 (만약, 자료형이 여러개라면 VO Class 생성!)
val data = ArrayList<String>()
data.add("돈까스")
data.add("제육볶음")
// 4. Adapter 결정
// (만약, TextView와 ArrayList<String> 사용한다면 ArrayAdapter사용가능)
// 1) 페이지 정보
// 2) 항목뷰 디자인
// 3) TextView의 id
// 4) data
val adapter = ArrayAdapter<String>(
this,
R.layout.lunch_list,
R.id.tvMenu,
data
)
// 5. Container 에 Adapter 부착
lvLunch.adapter = adapter
// 6. Event 처리
// 1) btnAdd를 눌렀을 때, etAdd의 값을 가져와서
// 2) data에 추가!!
// 3) adapter 새로고침
btnAdd.text = "추가"
btnAdd.setTextSize(18F)
btnAdd.setOnClickListener {
data.add(etAdd.text.toString())
adapter.notifyDataSetChanged()
etAdd.text = null
}
btnResult.setOnClickListener {
val rd = Random()
val menu = rd.nextInt(data.size)
tvLunch.text = data.get(menu)
}
}
}
[activity.lunch.xml]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".LunchActivity">
<Button
android:id="@+id/btnResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/tvLunch"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="내일의 점심은?"
android:textAlignment="center"
android:textSize="32sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/btnResult" />
<EditText
android:id="@+id/etAdd"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintBottom_toTopOf="@+id/btnResult"
app:layout_constraintEnd_toStartOf="@+id/btnAdd"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btnAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toTopOf="@+id/btnResult"
app:layout_constraintEnd_toEndOf="parent" />
<ListView
android:id="@+id/lvLunch"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/etAdd"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
[MainActivity]
package com.example.ex20221129
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.TextView
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
class MainActivity : AppCompatActivity() {
lateinit var tvResult: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//view의 id 값 찾아오기
tvResult = findViewById(R.id.tvResult)
val btnNext = findViewById<Button>(R.id.btnNext)
// btnNext를 눌렀을 때
btnNext.setOnClickListener {
//Intent 생성
val intent = Intent(this, SubActivity::class.java)
//Intent 실행 (SubActivity 이동 및 요청 )
// startActivityForResult(intent, 1004)
// requestCode: 결과값을 보내 줘야하는 Activity를 구분하기 위한 코드
launcher.launch(intent)
// 실행하려면 launch()키워드가 붙어줘야함 전달인자로 내가 생성한 intent 넣어주기
}
}//OnCreate 밖
//
// // Intent통해서 받아온 결과값을 처리할 수 있도록 도와주는 함수
// override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
// super.onActivityResult(requestCode, resultCode, data)
// // 1) requestCode : (1004) 내가 보낸 요청 코드를 받아오는 매개변수
// // 2) resultCode : RESULT_OK 받아온 결과값의 상태
// // 3) Intent? data : str(문구)가 붙어있는 Intent를 받아오는 매개변수
//
// // 내가 보냈던 요청이 맞는지 == 요청코드가 1004가 맞나요?
// if (requestCode==1004){
// // resultCode도 내가 원하는 결과값이 맞는지 (RESUIT_OK가 맞는지?)
// if(resultCode == RESULT_OK){
// // 두 가지다 만족하면 받아온 결과값을 처리 하겠습니다
// // tvResult의 text를 받아온 str로 바꾸자
// // 1. str꺼내기
// val str = data?.getStringExtra("content")
// // 2. TextView 내용을 str로 바꾸기
// tvResult.text = str
// }
// }
// }
// callback 함수
// 1. 다른 함수의 인자로 사용되는 함수
// 2. 어떤 이벤트에 의해 호출되어지는 함수 -> 버튼 클릭하면 Intent 실행시키면서 호출
// ActivityResultLauncher를 사용
// : 액티비티에서 데이터를 받아오기 위해 사용하는 함수
// : Fragment(부분화면)에서도 데이터를 주고받을 때 사용할 수 있음
// 기존에 ActivityForResult는 메모리가 너무 작음 -> 프로세스, 액티비티
// 소면될 수 있다
// 런처는 메모리부족으로 소멸되었다가 재생성해도 결과값을 받아온다
// Contract 자료형, 콜백메서드
val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
// 실제로 ActivityResultContracts를 타고 들어가면
// 1) createIntent --> StartActivityForResult 대체
// 2) parseResult --> onActivityResult 대체 (resultCode랑 Intent만 받아온다)
// 런처를 사용하게 되면 요청을 보낸 Activity를 구분할 필요가 없다
// requestCode가 필요없습니다!
// it에서 resultCode랑 data를 추출
// Log.d("data", it.toString())
Log.d("data", it.data.toString())
Log.d("data", it.resultCode.toString())
// ResultCode가 RESUIT_OK 인지 확인
if (it.resultCode == RESULT_OK){
tvResult.text = it.data?.getStringExtra("content")
// it.data --> Intent? 의 리턴값을 가지고 있다
}
}
}
[activity.main.xml]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<TextView
android:id="@+id/tvResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="250dp"
android:text="TextView"
android:textSize="34sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Button"
app:layout_constraintEnd_toEndOf="@+id/tvResult"
app:layout_constraintStart_toStartOf="@+id/tvResult"
app:layout_constraintTop_toBottomOf="@+id/tvResult" />
</androidx.constraintlayout.widget.ConstraintLayout>
[SubActivity]
package com.example.ex20221129
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
class SubActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sub)
//MainActivity에서 requestCode와 함께 Intent로 이동한 상태
val etResult = findViewById<EditText>(R.id.etResult)
val btnSend = findViewById<Button>(R.id.btnSend)
//btnSend를 눌렀을 때!
btnSend.setOnClickListener {
// 1. EditText에 적혀있는 문구를 가져온다
// 2. 문구를 변수에 저장한다
val str = etResult.text.toString()
// 3. Intent 생성한다
val intent = Intent()
// 4. Intent에 데이터(문구)를 붙혀준다 --> putExtra(key,value)
intent.putExtra("content",str)
// 5. setResult(resultCode, intent)
setResult(RESULT_OK, intent)
// resultCode: 결과값의 상태를 Main에서 판단하기위한 신호(코드)
// 6. finish()
finish()
}
}
}
[activity.sub.xml]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".SubActivity">
<EditText
android:id="@+id/etResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="250dp"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Button"
app:layout_constraintEnd_toEndOf="@+id/etResult"
app:layout_constraintStart_toStartOf="@+id/etResult"
app:layout_constraintTop_toBottomOf="@+id/etResult" />
</androidx.constraintlayout.widget.ConstraintLayout>
'Full Stack 교육 회고록' 카테고리의 다른 글
2022-12-01 - 안드로이드스튜디오 컬러팔레트 만들기 (0) | 2022.12.02 |
---|---|
2022.11.30 - 안드로이드 전화번호부, 포켓몬 도감 만들기 (0) | 2022.12.01 |
2022.11.28- 안드로이드 스튜디오 (0) | 2022.11.28 |
11/25- 안드로이드스튜디오(계산기, 로그인) / Node.js(Sequelize) (0) | 2022.11.25 |
11/24 node.js / kotlin (1) | 2022.11.24 |