728x90

출처: https://rudalskim.tistory.com/141 [rudalskim]

 

 

Progaurd 설정 파일이 어떤 경우에는 proguard-android.txt를 사용하고, 

또 다른 경우는 proguard-android-optimize.txt를 사용하고 있었습니다.


 buildTypes {
        release {
            minifyEnabled true    // Set it to true in order to enable ProGuard
            
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            또는
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

 

두 가지의 차이점이 궁금해서 검색해 보니 안드로이드의 platform SDK에서 발견할 수 있었습니다

차이점은 최적화 사용 유무에 따라 사용하지 않을 경우 proguard-android.txt를 사용하고, 최적화 옵션을 사용할 경우 proguard-android-optimize.txt를 사용하라고 되어 있습니다.

 

728x90
728x90

출처: https://kimyunseok.tistory.com/40

 

startActivityForResult() - Deprecated

 

변경전: A 액티비티와 B 액티비티가 있을 때,

startActivityResult메서드와 onActivityResult메서드를 사용해서 구현할 경우

  1. A -> B 실행, 메모리가 부족해서 A가 소멸됨.
  2. B 액티비티 종료 후 setResult() 메서드로 결과값 넘김
  3. A가 소멸됐다가 다시 생성돼서 B에게 결과값을 요청한 줄 모름.

변경후: ActivityResultLauncher객체와 registerForActivityResult()를 사용한 경우

  1. A -> B 실행, 메모리가 부족해서 A가 소멸됨.
  2. B 액티비티 종료 후 setResult() 메서드로 결과값 넘김

A가 다시 생성돼도 registerForActivityResult() 메서드가 다시 콜백을 등록해 줘서 결과값을 받아온다.

 

∴ ActivityResultLauncher객체와 registerForActivityResult()로 구현하면 됨

 

 

 

출처2:https://velog.io/@bonimddal2/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-ActivityResultLauncher%EB%A1%9C-startActivityForResult%EC%99%80-requestPermissions-%EB%8C%80%EC%B2%B4%ED%95%98%EA%B8%B0

출처3:https://aal-izz-well.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C%EC%BD%94%ED%8B%80%EB%A6%B0-activityResultLauncherActivityForResult-%EB%8C%80%EC%B2%B4

 

우선 implementation을 해준다.

implementation 'androidx.activity:activity:1.3.0-alpha08'
implementation 'androidx.fragment:fragment:1.4.0-alpha01'

==> 나는 아래로 변경함

implementation 'androidx.activity:activity-ktx:1.4.0'
implementation 'androidx.fragment:fragment-ktx:1.4.1'


ActivityResultLauncher 사용법은 아래와 같다.

class MainActivity : AppCompatActivity(), View.OnClickListener {
    val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }

    //ActivityResultLauncher<T>객체를 생성해주고 초기화 해준다.
    //T는 내가 호출할 엑티비티에서 결과값으로 받아올 자료형을 말한다.
    lateinit var activityResultLauncher: ActivityResultLauncher<Intent>
    val TAG = "MainActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        binding.btnMain.setOnClickListener(this)

        //RegisterActivityResult(Contract자료형, 콜백메서드)를 이용해서
        //ActivityResultLauncher를 초기화 해준다.
        activityResultLauncher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult())
            {//Result 매개변수 콜백 메서드
                //ActivityResultLauncher<T>에서 T를 intent로 설정했으므로
                //intent자료형을 Result 매개변수(콜백)를 통해 받아온다
                //엑티비티에서 데이터를 갖고왔을 때만 실행
                if (it.resultCode == RESULT_OK) {
                    //SubActivity에서 갖고온 Intent(It)
                    val myData: Intent? = it.data
                    val address = it.data?.getStringExtra("KEY1") ?: ""
                    Log.e(TAG, address)
                }
            }


    }


    override fun onClick(v: View?) {

        when (v?.id) {
            //버튼을 누르면 메뉴 엑티비티가 실행되게 하였다.
            //launch메서드를 이용해 intent를 실행하고 새 엑티비티로부터 응답을받는다.
            //그리고 RequestCode가 사라졌다.
            binding.btnMain.id -> {
                val intent = Intent(applicationContext, SubActivity::class.java)
                activityResultLauncher.launch(intent)
            }

            else -> {


            }
        }


    }


}

 

class SubActivity : AppCompatActivity(), View.OnClickListener {
    val binding by lazy { ActivitySubBinding.inflate(layoutInflater) }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        binding.btnSub.setOnClickListener(this)
    }


    //버튼 클릭 리스너 메서드
    override fun onClick(v: View?) {
        when (v?.id) {
            binding.btnSub.id -> {
                val intent = Intent(applicationContext, MainActivity::class.java).apply {
                    //엑티비티에서 갖고올 데이터
                    putExtra("KEY1", "bbbbb")
                    //데이터 전달이 성공했을 때의 변수 값 저장
                    // Result_ok = -1 일 때 엑티비티에 전달된다.

                }
                setResult(RESULT_OK, intent)
                //엑티비티 종료
                if (!isFinishing) finish()
            }
            else -> {
            }
        }
    }

}

 

 

728x90
728x90

 

1. 기존 legacy 프로젝트를 많이 유지보수 하는 관계로, 네트워크 클래스가 async task로 구현된걸 발견..

사실 절망에 빠져있는 상황인데...

 

Async Task를 대체할 방안은 찾아보니 대체로 두가지였다.

1) RxJava, RxKotlin 등 비동기처리를 Rx기반으로 변경

2) Kotlin의 Coroutine 이용

 

2. 그러나 현재 legacy 프로젝트는 전부 Java이고, 신규메뉴만 Kotlin도 아니고 핵심 네트워크 클래스를 Kotlin으로 변경하면 연결된 Java코드들에서도 무난하게 다 돌아가는지... 순전히 경험미숙으로 걱정 중

 

- 기존 레거시 프로젝트: Java기반, HttpUrlConnection+Async Task를 사용

- 토이 프로젝트: Kotlin 기반, Retrofit 사용 

 

찾아보니 Retrofit은 AsyncTask를 사용하지 않는 관계로, 굳이 해당 부분을 전부 수정할 필요는 없는 듯 하다.

 

"Retrofit의 장점은 속도, 편의성, 가독성이 있다. 가장 비교하기 좋은 Okhttp는 사용시 대개 Asynctask를 통해 비동기로 실행하게 되는데 Asynctask가 성능상 느리다는 이슈가 있었다. Retrofit에서는 Asynctask를 사용하지 않고 자체적인 비동기 실행과 스레드 관리를 통해 속도를 훨씬 빠르게 끌어올렸다. 약 3~10배 차이가 난다고 한다."

 

"앱-서버 통신을 Okhttp 라이브러리로 AsyncTask를 사용하여 구현했다고 할 수도 있다. 하지만 AsyncTask 로 서버와 통신을 구현하는 것은 어렵고 시간이 많이 들 뿐만 아니라(비동기 처리 코드를 개발자가 하나하나 작성), AsyncTask 자체가 안드로이드에서 deprecated 되었다. 그래서 이제 AsyncTask 를 사용하여 서버 통신을 구현하는 것은 좋은 생각이 아니다. 

그대신, retrofit 을 사용하는 것이 가독성도 좋고 훨씬 간편하고 쉽고, 빠르기 때문에 retrofit 을 사용한다."

 

==> 그렇다면 레거시 프로젝트는 네트워크 클래스 부분을 Retrofit으로 변경하고, 그 외에 AsyncTask를 사용하는 부분은 RxJava로 수정하면 급한 불은 끌 수 있지 않을까 싶다.

 

 

Reference

woovictory.github.io/2019/01/03/Android-What-is-retrofit/

salix97.tistory.com/204

 

 

 

728x90
728x90

String Array로 형성한 데이터를 단일 String으로 합쳐야 할 경우,

kotlin에서는 joinToString을 사용하면 된다.

list.joinToString()

list.joinToString(separator = ":")

 

상세 예를 들면 아래와 같다.

val list = listOf("one", "two", "three", "four", "five")
println(
    list.joinToString(
        prefix = "[",
        separator = ":",
        postfix = "]",
        limit = 3,
        truncated = "...",
        transform = { it.toUpperCase() })

 

 

결과는

 

[ONE:TWO:THREE:...]

 

Reference

stackoverflow.com/questions/56515172/best-way-to-convert-arraylist-to-string-in-kotlin

728x90

+ Recent posts