본문 바로가기

Full Stack 교육 회고록

2022.11.29 안드로이드스튜디오

728x90
SMALL

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>

 

728x90
LIST