ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 1-5. View(Activity)에서 ViewModel의 LiveData를 옵져빙
    카테고리 없음 2021. 9. 14. 18:42
    • activity_memo_list.xml
    <?xml version="1.0" encoding="utf-8"?>
    <layout 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">
    
        <data>
            <variable
                name="viewModel"
                type="com.project.memoapp.viemodel.AndroidViewModelMemoList"/>
        </data>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar_MemoListActivity"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="?attr/colorPrimary"
                android:minHeight="?attr/actionBarSize"
                android:theme="?attr/actionBarTheme" />
    
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recycler_MemoListActivity"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1" />
    
            <Button
                android:id="@+id/btn_goto_WriteMemoActivity"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right"
                android:onClick="onClick"
                android:text="메모추가" />
    
        </LinearLayout>
    </layout>

    데이터 바인딩을 사용하여 AndroidViewModel 바인딩 변수 viewModel을 선언하였는데

    현재는 사용되지 않으므로 없어도 상관없다.

    툴바는 없어도 상관없다. 나중에 기능을 만들기 위해서 추가해놨다.

    액티비티 코드의 툴바 설정도 마찬가지


    • ActivityMemoList

     

    리싸이클러뷰와 어댑터는 다음 포스팅에서 작성

     

    버튼을 누르면 메모 작성 액티비티로 이동. 액티비티가 종료되지 않은 채로 넘어감

     

    onStart에서 뷰모델의 LiveData를 옵져빙하여 변경시 어댑터를 설정하고 리싸이클러뷰 다시 그리기

     

    onRestart의 데이터베이스 쿼리

    메모를 작성하고 기존 액티비티로 돌아왔을때 메모 데이터 베이스가 변경되므로 Model의 데이터베이스 쿼리를 통해 Model의 라이브 데이터를 재설정되도록하여 Model의 LiveData가 ViewModel에 통지되고

    ViewModel의 LiveData가 변경되어 View에게 다시 통지된다.

     

    안드로이드에서 기본으로 제공해주는 AndroidViewModel 팩토리를 사용하여 뷰모델 생성

    class MemoListActivity : AppCompatActivity(), View.OnClickListener {
    
        lateinit private var binding: ActivityMemoListBinding
        private var mActionBar: ActionBar? = null
        lateinit private var mViewModel: AndroidViewModelMemoList
    
        lateinit private var mAdapter: AdapterMemoList
    
        override fun onCreate(savedInstanceState: Bundle?) {
            printLog("onCreate")
            super.onCreate(savedInstanceState)
    
            //시스템 configuration변경시 Activity는 recreated지만 연결된 ViewModel은 살아있음.
            if (savedInstanceState == null) {
                //액티비티가 최초로 생성될 때만 ViewModel생성
    
                //DataBinding and return binding instance
                binding = DataBindingUtil.setContentView(this, R.layout.activity_memo_list)
    
                //ViewModel 초기화
                mViewModel =
                    ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory(application))
                        .get(AndroidViewModelMemoList::class.java)
    
    
                //set Toolbar
                setSupportActionBar(binding.toolbarMemoListActivity)
                mActionBar = supportActionBar
            } else {
                //시스템 configuration 변경-> 액티비티가 recreated일때
            }
    
        }
    
        override fun onStart() {
            super.onStart()
            printLog("onStart")
    
            //RoomDatabase준비
            mViewModel.repositoryMemo.querySelectAllDefault()
    
            //RecyclerView와 Adapter
            binding.recyclerMemoListActivity.layoutManager = LinearLayoutManager(this)
    
            val dataObserver: Observer<List<Memo>> = Observer { memos ->
                //RecyclerView 셋팅
                mAdapter = AdapterMemoList(this, memos)
                binding.recyclerMemoListActivity.adapter = mAdapter
                mAdapter.notifyDataSetChanged()
    
            }
            mViewModel.liveMemos.observe(this, dataObserver)
    
        }
        
        //WriteMemoActivity로 갔다가 메모를 작성하고 돌아올때 다시 액티비티가 foreground된 경우
        //메모를 작성했을 수도 있기때문에 Model에서 메모를 다시 뽑아오도록 한다.
        override fun onRestart() {
            super.onRestart()
            printLog("onRestart")
            mViewModel.repositoryMemo.querySelectAllDefault() //메모 작성했기 떄문에 다시 db에서 쿼리
        }
    
        override fun onStop() {
            super.onStop()
            printLog("onStop")
    
            //RoomDatabase는 다른 액티비티에서 사용하므로 onStop에서는 그냥 놔둠
        }
    
        override fun onDestroy() {
            printLog("onDestroy")
            super.onDestroy()
    
        }
    
        override fun onClick(v: View?) {
            if (v != null) {
                val selected: Int = v.id
                when (selected) {
                    binding.btnGotoWriteMemoActivity.id -> {
                        var intent: Intent = Intent(this, WriteMemoActivity::class.java)
                        startActivity(intent)
                    }
                }
            }
        }
    
        fun printLog(str: String) {
            Log.d("APPLICATIONTEST", "MemoListActivity: $str")
        }
    }

    recycler_item_write_memo.xml 리싸이클러 뷰의 아이템으로 들어갈 뷰에 해당하는 layout

    <?xml version="1.0" encoding="utf-8"?>
    
    <LinearLayout 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="wrap_content"
        android:orientation="vertical"
        android:paddingStart="3dp"
        android:paddingTop="2dp"
        android:paddingEnd="3dp"
        android:paddingBottom="2dp">
    
        <androidx.cardview.widget.CardView
            android:id="@+id/cardView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:cardCornerRadius="5dp"
            app:cardElevation="5dp">
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                tools:context=".ui.MemoListActivity">
    
                <TextView
                    android:id="@+id/tv_title"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="5"
                    android:textSize="20sp"
                    tools:text="제목" />
    
                <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:orientation="vertical">
    
                    <TextView
                        android:id="@+id/tv_createdDate"
                        android:layout_width="match_parent"
                        android:layout_height="0dp"
                        android:layout_weight="1"
                        android:gravity="right"
                        android:text="TextView"
                        android:textSize="10sp"
                        tools:text="2021. 08. 10" />
    
    
                    <TextView
                        android:id="@+id/tv_createdTime"
                        android:layout_width="match_parent"
                        android:layout_height="0dp"
                        android:layout_weight="1"
                        android:gravity="right"
                        android:textSize="10sp"
                        tools:text="오후 9:34" />
                </LinearLayout>
            </LinearLayout>
        </androidx.cardview.widget.CardView>
    
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="2dp"
            android:background="#e2e2e2" />
    </LinearLayout>

     

    RecyclerView.Adapter

    //Adapter는 View, Adapter의 data source는 ViewModel
    class AdapterMemoList(val context: Context, var memos: List<Memo>) :
        RecyclerView.Adapter<AdapterMemoList.Holder>() {
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
            val view = LayoutInflater.from(context).inflate(R.layout.recycler_item_memo, parent, false)
            return Holder(view)
        }
    
        override fun getItemCount(): Int {
            return memos.size
        }
    
        override fun onBindViewHolder(holder: Holder, position: Int) {
            holder.bind(memos[position])
        }
    
        inner class Holder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            val title = itemView.findViewById<TextView>(R.id.tv_title)
            val createdDate = itemView.findViewById<TextView>(R.id.tv_createdDate)
            val createdTime = itemView.findViewById<TextView>(R.id.tv_createdTime)
    
            fun bind(memo: Memo) {
                title.text = memo.title
                createdDate.text = memo.created?.substring(0, 10)
                createdTime.text = memo.created?.substring(11, 19)
            }
        }
    }

    데이터 바인딩은 사용하지 않았다. 기능이 잘 동작되었기 떄문에 이제 적용해보려고 한다.

     

    다음 포스팅- 메모를 작성 액티비티 , 그와 관련된 뷰 모델

    댓글

Designed by Tistory.