본문 바로가기
Programando/Android

[Android/Kotlin] ViewPager2, Remote Config_(7)

ViewPager2

ViewPager는 Horizontal Orientation만 지원해 가로 스와이프만 가능했지만, ViewPager2는 Vertical Orientation 또한 지원해 세로 스와이프도 가능해졌다. 또한 기존의 ViewPager에 비해 Modifiable Fragment가 개선되었다. 또, 기존의 ViewPager와 다르게 리사이클러뷰를 기반으로 작업이 되었기 때문에 애니메이션과 같은 작업을 더욱 원활히 보여줄 수 있다.

 

1. Dependencies 추가

- 앱 모듈의 build.gradle의 dependencies에 해당 코드를 작성한다.

dependencies {

    implementation 'com.google.android.material:material:1.3.0'
    
}

 

2. xml에 ViewPager2 코드 추가

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/ViewPager2"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

 

3. ViewPager2 어댑터 생성

- 실제로 랜더링하는 부분을 구현하는 코드이다. 어댑터는 리사이클러뷰의 어댑터를 사용한다.

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class QuotesPagerAdapter(
    private val quotes: List<Quote>
): RecyclerView.Adapter<QuotesPagerAdapter.QuoteViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
        QuoteViewHolder(
            LayoutInflater.from(parent.context)
                .inflate(R.layout.item_quote, parent, false)
        )

    override fun onBindViewHolder(holder: QuoteViewHolder, position: Int) {
        holder.bind(quotes[position])
    }

    override fun getItemCount() = quotes.size

    class QuoteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        private val quoteTextView: TextView = itemView.findViewById(R.id.tv_quote)
        private val nameTextView: TextView = itemView.findViewById(R.id.tv_name)

        // Holder 안에 bind method를 구현
        fun bind(quote:Quote) {
            quoteTextView.text = quote.quote
            nameTextView.text = quote.name
        }

    }

}

 

4. 코틀린 파일에서 데이터 추가

- QuotesPagerAdapter을 지정하고, 데이터 리스트를 추가한다.

    private val viewPager: ViewPager2 by lazy {
        findViewById(R.id.vp2)
    }
        viewPager.adapter = QuotesPagerAdapter(
                listOf(
                        Quote(
                                "나는 생각한다. 고로 나는 존재한다.",
                                "데카르트"
                        ),
                        Quote(
                                "자신감은 전염된다. 자신감의 부족도 마찬가지다.",
                                "빈스 롬바르디"
                        )
                )
        )

 

Remote Config

앱 업데이트를 게시하지 않아도 하루 활성 사용자 수 제한 없이 무료로 앱의 동작과 모양을 변경할 수 있다.

 

- 비율 출시 메커니즘을 사용한 새 기능 출시
앱에서 새로운 기능을 업데이트해서 출시했는데 사용자에게 바로 배포하기에는 부담스러울 때, 조건으로 비율을 정해서 10%의 사용자에게 노출하고, 30%의 사용자에게 노출하는 등 점진적으로 노출을 하면서 기능의 동작을 확인한다.

- 앱의 플랫폼 및 언어별 프로모션 배너 정의
이 타이밍에 이런 문구의 알림을 보여주고 싶다. 싶을 때 업데이트 없이 이미지나 홍보 문자, 안내 문자를 변경할 수 있다.

- 제한된 테스트 그룹에서의 새 기능 테스트
두 개 이상의 테스트 그룹에게 독립적으로 각각 다른 환경을 제공해서 실험을 해서 비교를 할 수 있다.

 

1. Firebase 프로젝트 생성

 

2. Dependencies 추가

- 프로젝트 모듈의 build.gradle의 dependencies에 해당 코드를 작성한다.

dependencies {

    classpath 'com.google.gms:google-services:4.3.10'
    
}

 

- 앱 모듈의 build.gradle에도 해당 코드를 작성한다.

apply plugin: 'com.google.gms.google-services'

dependencies {

    implementation platform('com.google.firebase:firebase-bom:26.5.0')
    implementation 'com.google.firebase:firebase-config-ktx'
    implementation 'com.google.firebase:firebase-analytics-ktx'
    
}

 

2. Remote Config 설정

- 파이어베이스의 프로젝트 화면의 왼쪽에서  Remote Config 를 클릭하고,

 

- Remote Config의 화면에서  구성 추가하기 를 통해 매개변수를 생성한다. 매개변수 이름(키)를 설정하고, Default value의  { } 를 클릭해서 JSON을 생성한 후,  저장 을 한다.

[
  {
    "quote": "자신감은 전염된다. 자신감의 부족도 마찬가지다.",
    "name": "빈스 롬바르디"
  },
  {
    "quote": "삶이 있는 한 희망은 있다",
    "name": "키케로"
  },
  {
    "quote": "고통이 남기고 간 뒤를 보라! 고난이 지나면 반드시 기쁨이 스며든다.",
    "name": "괴테"
  },
  {
    "quote": "사막이 아름다운 것은 어딘가에 샘이 숨겨져 있기 때문이다.",
    "name": "생텍쥐베리"
  },
  {
    "quote": "행복의 한 쪽 문이 닫히면 다른 쪽 문이 열린다. 그러나 흔히 우리는 닫혀진 문을 오랫동안 보기 때문에 우리를 위해 열려 있는 문을 보지 못한다.",
    "name": "헬렌 켈러"
  },
  {
    "quote": "인생에 뜻을 세우는데 있어 있는 때라곤 없다.",
    "name": "볼드윈"
  },
  {
    "quote": "실패는 잊어라. 그러나 그것이 준 교훈은 절대 잊으면 안 된다.",
    "name": "하버트 개서"
  } 
]

 

변경사항 게시 를 한다.

 

3. Remote Config 연동

    private fun initData() {
        val remoteConfig = Firebase.remoteConfig
        remoteConfig.setConfigSettingsAsync(
            // 비동기로 세팅
            remoteConfigSettings {
                minimumFetchIntervalInSeconds = 0
                // 서버에서 블락하지 않는 이상 앱을 들어올 때마다 곧바로 fetch가 실행된다.
            }
        )
        // fetch 자체가 서버와 통신을 하는 것이기 때문에 리스너를 등록해야 한다.
        remoteConfig.fetchAndActivate().addOnCompleteListener {
            // Task를 완료했다는 의미
            if(it.isSuccessful) { // Task가 성공했다면
                val quotes = parseQuotesJson(remoteConfig.getString("quotes"))
                val isNameRevealed = remoteConfig.getBoolean("is_name_revealed")

                displayQuotesPager(quotes, isNameRevealed)

            }
        }
    }
    
    private fun parseQuotesJson(json: String):List<Quote> {
        val jsonArray = JSONArray(json)
        var jsonList = emptyList<JSONObject>()

        for(index in 0 until jsonArray.length()) {
            val jsonObject = jsonArray.getJSONObject(index)
            jsonObject?.let {
                jsonList = jsonList + it
            }
        }

        return jsonList.map {
            Quote(
                it.getString("quote"),
                it.getString("name"))
        }
    }

    private fun displayQuotesPager(quotes:List<Quote>, isNameRevealed: Boolean) {
        viewPager.adapter = QuotesPagerAdapter(
                quotes
        )
    }
반응형