Android App/Kotlin

스레드생성 및 통신(Runnable, Handler), SharedPreferences사용

AppJinny 2023. 1. 15. 18:37

*스레드생성 및 통신(Runnable, Handler), SharedPreferences사용

-Runnable 인터페이스 구현하여 스레드 생성 : 상속관계에 있는 클래스도 구현할 수 있도록 지원(코틀린 언어의 특성상 다중상속을 허용하지 않음)

--스레드생성 다른방법 참고 : https://heeyjinny.tistory.com/93

-핸들러(Handler)를 사용해 메인스레드와 백그라운드 스레드 연결

--스레드간 통신방법 참고 : https://heeyjinny.tistory.com/94

-SharedPreferences를 사용하여 내부 저장소 이용(권한 설정 필요없음), 간단한 코드로 사용

--SharedPreferences 참고 : https://heeyjinny.tistory.com/84

 

 

*스레드(Thread)-백그라운드 스레드

-메모리 이외의 다른 곳에서 데이터를 가져오는 작업 처리

-네트워크 작업, 파일 업로드 및 다운로드, 이미지 처리, 데이터 로딩 등은 백그라운드 스레드에서 처리하는 것을 권장

-백그라운드 스레드로 메인 스레드에 집중될 수 있는 코드를 분산함으로써 효율적인 앱을 만들 수 있음

-주의할 점 : 백그라운드 스레드는 UI구성요소에 접근하면 안되는 제약조건을 가지고 있음

-UI를 담당하는 메인 스레드에 접근하려면 핸들러(Handler)사용

 

*핸들러(Handler)

-새로 생성된 스레드들과 메인 스레드와의 통신 담당

-루퍼가 있는 메인 스레드 에서 주로 사용됨

-핸들러는 루퍼를 통해 전달되는 메시지를 받아 처리하는 일종의 명령어 처리기

-루퍼는 앱 실행 시 자동 생성되지만 핸들러는 개발자가 직접 생성해 사용

 

*SharedPreferences(내부 저장소 사용)

-안드로이드 플랫폼은 간단한 데이터 저장 목적으로 SharedPreferences를 제공

-주로 로그인 정보나 앱의 상태 정보를 저장하는 용도로 사용됨

-액티비티에서 인텐트에 값을 넣고 빼는 것과 비슷한 형태로 동작

-인텐트에 값을 전달하듯이 데이터를 키와 값 쌍으로 저장

-데이터는 XML형식으로 된 파일로 저장되고 앱이 종료되어도 남아있음

 

*Runnable, Handler, SharedPreferences 사용하기

class DiaryActivity : AppCompatActivity() {

    //3-3
    //메인 스레드에 연결되어 있는 핸들러 생성
    val handler = Handler(Looper.getMainLooper())

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_diary)

        //1
        //다이어리 액티비티의 뷰가 실행되었을 때
        //내부 저장소에서 저장되어있는 내용을 가져와 화면 에디트텍스트에 보여주기
        //SharedPreferences사용하여 내부 저장소 파일에 데이터 저장...

        //1-1
        //레이아웃의 에디트텍스트 연결
        val etContent = findViewById<EditText>(R.id.etContent)

        //1-2
        //getSharedPreferences를 하여 컨텐츠파일의 내용 가져와 변수에 저장
        val contentPreferences = getSharedPreferences("content", Context.MODE_PRIVATE)

        //1-3
        //에디트텍스트에 가져온 내용을 문자열로 저장하기
        //getString(파일명, 기본값)
        etContent.setText(contentPreferences.getString("content", ""))

        //3
        //다이어리 텍스트가 한 글자씩 변경될 때마다
        //내용을 저장을 위해 계속 실행되기 때문에 실행 낭비가 됨
        //효율성을 높이기 위해 글 작성 중 지정 시간동안 멈출 때마다 저장되도록
        //백그라운드에서 작동하는 스레드 기능 이용하기

        //3-1
        //백그라운드 스레드에 넣을 때 Runnable 인터페이스 사용***
        val runnable = Runnable {
            //3-2
            //저장소에 내용을 비동기(apply)로 저장하기
            contentPreferences.edit {
                putString("content", etContent.text.toString())
            }
            
            //3-3
            //새로 생성한 백그라운드 스레드는 UI에 접근할 수 없기 때문에
            //Handler를 사용하여 메인스레드와 연결하여 UI에 접근하여 수정할 수 있음
            //전역변수로 핸들러 생성...
            
            //로그로 텍스트 저장이 잘 되는지 확인
            Log.d("DiaryActivity", "TextSaved ${etContent.text.toString()}")

        }//runnable

        //2
        //다이어리 컨텐츠의 텍스트 내용이 변경될 때마다
        //변경된 내용을 저장하기 위해 호출하는 기능 사용
        //.addTextChangedListener{}
        etContent.addTextChangedListener {
        
            //4
            //백그라운드 스레드에서 일어나는 기능 구현하고
            //비동기로 저장한 내용을 핸들러를 이용해 메인과 백그라운드 연결 후
            //Hadler기능 중 postDelay기능을 사용하여
            //지정된 시간 후에 백그라운드 스레드의 기능이 구현되도록 설정

            //0.5초 이내에 텍스트 체인지가 계속 일어나고 있다면
            //runnable의 동작 실행이 되지 않도록 .removeCallbacks()
            //만약 0.5초 이상 텍스트가 변경되지 않았다면
            //핸들러를 이용해 runnable의 동작이 수행되면서 내부저장소에 저장됨
            //로그로 텍스트 변경이 잘 되는지 확인
            Log.d("DiaryActivity", "TextChanged :: $it")

            //4-1
            //이전에 백그라운드스레드(runnable)이 진행되고 있다면
            //지우고 다시 실행되도록...
            handler.removeCallbacks(runnable)
            //4-2
            //0.5초(500밀리초) 후에 핸들러를 이용하여 백그라운드 스레드(변수 runnable)기능 동작
            handler.postDelayed(runnable, 500)
        }

    }//onCreate
}//DiaryActivity