{"id":299,"date":"2018-05-07T01:20:41","date_gmt":"2018-05-06T16:20:41","guid":{"rendered":"http:\/\/www.charlezz.com\/?p=299"},"modified":"2019-07-22T23:53:17","modified_gmt":"2019-07-22T14:53:17","slug":"reactive-programing5-%ec%95%88%eb%93%9c%eb%a1%9c%ec%9d%b4%eb%93%9c%ec%97%90%ec%84%9c%ec%9d%98-rxjava-%ed%99%9c%ec%9a%a9","status":"publish","type":"post","link":"https:\/\/charlezz.com\/?p=299","title":{"rendered":"Reactive Programing(5) \u2013 \uc548\ub4dc\ub85c\uc774\ub4dc\uc5d0\uc11c\uc758 RxJava \ud65c\uc6a9"},"content":{"rendered":"<h1><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1000\/1*NkhhBPaaZXD9NSYC_xQ0LA.png\" width=\"1000\" height=\"562\" \/><\/h1>\n<hr \/>\n<p><a href=\"https:\/\/www.charlezz.com\/?p=189\">Reactive Programing(1) &#8211; \ub9ac\uc561\ud2f0\ube0c \ud504\ub85c\uadf8\ub798\ubc0d \uac1c\ub150\uc7a1\uae30<\/a><br \/>\n<a class=\"row-title\" href=\"https:\/\/www.charlezz.com\/?p=242\" aria-label=\"\u201cReactive Programing(2) \u2013 Reactive Operator\u201d (\ud3b8\uc9d1)\">Reactive Programing(2) \u2013 Reactive Operator<\/a><br \/>\n<a class=\"row-title\" href=\"https:\/\/www.charlezz.com\/?p=264\" aria-label=\"\u201cReactive Programing(3) \u2013 Reactive Operator\u201d (\ud3b8\uc9d1)\">Reactive Programing(3) \u2013 Reactive Operator<\/a><br \/>\n<a class=\"row-title\" href=\"https:\/\/www.charlezz.com\/?p=283\" aria-label=\"\u201cReactive Programing(4) \u2013 Scheduler\u201d (\ud3b8\uc9d1)\">Reactive Programing(4) \u2013 Scheduler<\/a><br \/>\nReactive Programing(5) \u2013 \uc548\ub4dc\ub85c\uc774\ub4dc\uc5d0\uc11c\uc758 RxJava \ud65c\uc6a9<\/p>\n<hr \/>\n<h1>\uc548\ub4dc\ub85c\uc774\ub4dc\uc5d0\uc11c RxJava2 \uc0ac\uc6a9\ud558\uae30<\/h1>\n<p>\u00a0<br \/>\n\uc790\ubc14\ub294 \ud568\uc218\ud615 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \uc81c\ub300\ub85c \uc9c0\uc6d0\ud558\uc9c0 \ubabb\ud558\uace0 \uc788\uc73c\uba70, \uc5ec\uc804\ud788 Side Effect(\ubd80\uc218\ud6a8\uacfc)\ub97c \uc644\ubcbd\ud558\uac8c \uc81c\uac70\ud558\uc9c0 \ubabb\ud588\ub2e4.<br \/>\n\uc774\ub7ec\ud55c \uc774\uc720\ub85c \uc548\ub4dc\ub85c\uc774\ub4dc\uc5d0\uc11c RxJava2\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 RxAndroid \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \ub4f1\uc7a5\ud558\uac8c \ub418\uc5c8\ub2e4.<br \/>\n\u00a0<\/p>\n<h2>RxAndroid\ub780?<\/h2>\n<p>\uae30\ubcf8\uc801\uc73c\ub85c\ub294 RxJava2\uac00 \ubc14\ud0d5\uc774 \ub418\uba70, \uc548\ub4dc\ub85c\uc774\ub4dc\uc5d0\uc11c \ud544\uc694\ud55c \uba87\uba87 \ud074\ub798\uc2a4\ub97c \ucd94\uac00\ud55c \ub77c\uc774\ube0c\ub7ec\ub9ac \uc785\ub2c8\ub2e4.<br \/>\n\uc548\ub4dc\ub85c\uc774\ub4dc \uc571 \uac1c\ubc1c\uc2dc \uc5b4\ub824\uc6c0\uc744 \uacaa\ub294 \ubb38\uc81c \uc911 \ud558\ub098\uac00 \uba40\ud2f0\uc2a4\ub808\ub4dc \uc0ac\uc6a9\uc785\ub2c8\ub2e4.<br \/>\n\uba40\ud2f0\uc2a4\ub808\ub4dc \uc0ac\uc6a9\uc2dc 2\uac1c\uc774\uc0c1\uc758 \ube44\ub3d9\uae30 \ucc98\ub9ac, \uc5d0\ub7ec\ucc98\ub9ac,\ud578\ub4e4\ub7ec, \ucf5c\ubc31, \uc774\ubca4\ud2b8 \uc911\ubcf5 \ub4f1 \ubcf5\uc7a1\ud55c \ucc98\ub9ac\ub97c \ud560 \uc218 \ubc16\uc5d0 \uc5c6\uace0 \uc774\ub85c\uc778\ud574 \uac1c\ubc1c\uc5d0 \ub9ce\uc740 \uc790\uc6d0\uc774 \ud22c\uc785\ub429\ub2c8\ub2e4.<br \/>\nRxAndroid\ub294 \uc774\ub7ec\ud55c \ubb38\uc81c\ub97c \uc27d\uac8c \ud574\uacb0\ud574 \uc904 \uac83\uc785\ub2c8\ub2e4.<br \/>\n\u00a0<\/p>\n<h2>RxAndroid \uc124\uce58\ud558\uae30<\/h2>\n<p>\u00a0<br \/>\n\uc571\ub808\ubca8\uc5d0 build.gradle\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \uc758\uc874\uc131\uc744 \ucd94\uac00\ud569\ub2c8\ub2e4.<\/p>\n<pre class=\"lang:default decode:true\">implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'\r\nimplementation 'io.reactivex.rxjava2:rxjava:2.1.13'<\/pre>\n<p>\ucc38\uace0\ub85c RxAndroid\ub294 RxJava2\ub97c \ucc38\uc870\ud558\uace0 \uc788\uc5b4 \ubc18\ub4dc\uc2dc RxJava2\uc758 \uc758\uc874\uc131\uc744 \ucd94\uac00 \ud560 \ud544\uc694\ub294 \uc5c6\uc2b5\ub2c8\ub2e4.<br \/>\n\ud558\uc9c0\ub9cc \ucd5c\uc2e0\ubc84\uc804\uc758 RxJava\uc0ac\uc6a9\uc744 \uc704\ud574 \uba85\uc2dc\ud574\uc8fc\ub294\uac83\uc774 \uc88b\uc2b5\ub2c8\ub2e4.<br \/>\n\ucd5c\uc2e0\ubc84\uc804\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac \uc774\uc6a9\uc740 \uc544\ub798\uc758 \ub9c1\ud06c\ub97c \ucc38\uc870\ud574\uc8fc\uc138\uc694.<br \/>\n\ucc38\uc870\ub9c1\ud06c : <a href=\"https:\/\/github.com\/ReactiveX\/RxAndroid\">https:\/\/github.com\/ReactiveX\/RxAndroid<\/a><br \/>\n\u00a0<\/p>\n<h2>RxAndroid\uc758 \uae30\ubcf8<\/h2>\n<p>\uae30\ubcf8\uc801 \uad6c\uc131\uc694\uc18c\ub294 RxJava2\uc640 \uac19\uc544 \ub0b4\uc6a9\uc744 \uc0dd\ub7b5\ud558\uace0, RxAndroid\uc5d0\uc11c \ucd94\uac00\ub41c \uae30\ub2a5 \uc704\uc8fc\ub85c \uc124\uba85\ud558\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<h3>RxAndroid\uc758 \uc2a4\ucf00\uc904\ub7ec<\/h3>\n<table id=\"tablepress-7\" class=\"tablepress tablepress-id-7\">\n<thead>\n<tr class=\"row-1 odd\">\n<th class=\"column-1\">\uc2a4\ucf00\uc974\ub7ec<\/th>\n<th class=\"column-2\">\uc124\uba85<\/th>\n<\/tr>\n<\/thead>\n<tbody class=\"row-hover\">\n<tr class=\"row-2 even\">\n<td class=\"column-1\">newThread()<\/td>\n<td class=\"column-2\">\uc0c8\ub85c\uc6b4 \uc2a4\ub808\ub4dc \uc0dd\uc131<\/td>\n<\/tr>\n<tr class=\"row-3 odd\">\n<td class=\"column-1\">single()<\/td>\n<td class=\"column-2\">\ub2e8\uc77c \uc2a4\ub808\ub4dc \uc0dd\uc131 \ud6c4 \uc0ac\uc6a9<\/td>\n<\/tr>\n<tr class=\"row-4 even\">\n<td class=\"column-1\">computation()<\/td>\n<td class=\"column-2\">\uacc4\uc0b0\uc6a9 \uc2a4\ub808\ub4dc<\/td>\n<\/tr>\n<tr class=\"row-5 odd\">\n<td class=\"column-1\">io()<\/td>\n<td class=\"column-2\">\ub124\ud2b8\uc6cc\ud06c, \ud30c\uc77c \uc785\ucd9c\ub825 \uc2a4\ub808\ub4dc<\/td>\n<\/tr>\n<tr class=\"row-6 even\">\n<td class=\"column-1\">trampoline()<\/td>\n<td class=\"column-2\">\ud604\uc81c \uc2a4\ub808\ub4dc\uc5d0 \ub300\uae30\ud589\ub82c \uc0dd\uc131<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><!-- #tablepress-7 from cache --><br \/>\n\u00a0<\/p>\n<h3>UI \uc774\ubca4\ud2b8 \ucc98\ub9ac<\/h3>\n<p>\uc0ac\uc6a9\uc790\ub294 \ub300\ubd80\ubd84 View\ub97c \ud074\ub9ad\ud558\ub294\uac83\uc73c\ub85c \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \uc0c1\ud638\uc791\uc6a9\ud558\uac8c \ub429\ub2c8\ub2e4.<br \/>\n\ub2e4\uc74c \uc608\uc81c\ub97c \ubcf4\uba74\uc11c \uc5b4\ub5bb\uac8c Observable\uc744 \ud65c\uc6a9\ud558\ub294\uc9c0 \uc0b4\ud3b4\ubcf4\uc2dc\uae30 \ubc14\ub78d\ub2c8\ub2e4.<\/p>\n<pre class=\"lang:java decode:true\">Observable.create&lt;View&gt; { text_view.setOnClickListener(it::onNext) }\r\n        .map {\r\n            \"TextView is clicked\"\r\n        }\r\n        .subscribe {\r\n            Log.e(TAG, it)\r\n        }<\/pre>\n<p>kotlin-android-extension\uc744 \ud50c\ub7ec\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uace0 \uc788\uc5b4 id\ub85c View\ub97c \ucc38\uc870 \ud560 \uc218 \uc788\ub294 \uc0c1\ud0dc\uc785\ub2c8\ub2e4.<br \/>\ntext_view\ub77c\ub294 \uc544\uc774\ub514\ub97c \uac00\uc9c4 TextView\ub97c \ubbf8\ub9ac \ub9cc\ub4e4\uc5c8\uc2b5\ub2c8\ub2e4.<br \/>\ncreate\ud568\uc218\ub97c \ud1b5\ud574 Observable\uc744 \uc0dd\uc131\ud558\uace0 text_view\uac00 \ud074\ub9ad\ub418\uc5c8\uc744\ub54c \ub370\uc774\ud130\ub97c \ubc1c\ud589\ud558\ub3c4\ub85d \ud588\uc2b5\ub2c8\ub2e4.<br \/>\n\u00a0<\/p>\n<h3>\uc2e4\uc2dc\uac04 \ud0a4\uc6cc\ub4dc \uac80\uc0c9 \uad6c\ud604\ud558\uae30<\/h3>\n<p>\ud0a4\uc6cc\ub4dc\ub97c \uc785\ub825\ud558\uace0 \uc81c\ud55c\ub41c \uc2dc\uac04\ub0b4\uc5d0 \uc785\ub825\uc774 \uc5c6\uc73c\uba74 \uac80\uc0c9\uc744 \uc2dc\uc791\ud558\ub294 \ucf54\ub4dc\ub97c \ub9cc\ub4e4\uc5b4\ubcf4\ub3c4\ub85d \ud558\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<pre class=\"\">val source = Observable.create&lt;CharSequence&gt; { emitter -&gt;\r\n    edit_text.addTextChangedListener(object : TextWatcher {\r\n        override fun afterTextChanged(s: Editable?) {\r\n        }\r\n        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {\r\n        }\r\n        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {\r\n            s?.let {\r\n                emitter.onNext(it)\r\n            }\r\n        }\r\n    })\r\n}\r\nsource.debounce(3000L, TimeUnit.MILLISECONDS)\r\n        .filter { !TextUtils.isEmpty(it) }\r\n        .observeOn(AndroidSchedulers.mainThread()) \/\/Toast must be running on UI Thread\r\n        .subscribe {\r\n            Toast.makeText(this, \"searching =&gt; $it\",Toast.LENGTH_SHORT).show()\r\n        }<\/pre>\n<p>debounce\ud568\uc218\ub97c \ud1b5\ud574 3000ms \ub0b4\uc5d0 \uc785\ub825\uc774 \uc5c6\uc73c\uba74 \ud574\ub2f9 \ud0a4\uc6cc\ub4dc\ub97c \uac80\uc0c9\ud569\ub2c8\ub2e4.<br \/>\nfilter\ub97c \ud1b5\ud574 \ube48 \ubb38\uc790\uc5f4\uc740 \ucd9c\ub825\ud558\uc9c0 \uc54a\ub3c4\ub85d \ud588\uc2b5\ub2c8\ub2e4.<br \/>\n\uc774\ubc88\uc5d0\ub294 Log\uac00 \uc544\ub2cc Toast\ub97c \uc774\uc6a9\ud588\uc2b5\ub2c8\ub2e4. \ub85c\uadf8\ub294 \uc4f0\ub808\ub4dc\uc640 \uad00\uacc4 \uc5c6\uc774 \ucd9c\ub825\ub418\uc9c0\ub9cc,<br \/>\nToast\ub294 UI\uc4f0\ub808\ub4dc(Main\uc4f0\ub808\ub4dc) \uc5d0\uc11c\ub9cc \uc791\ub3d9\ud558\uae30 \ub54c\ubb38\uc785\ub2c8\ub2e4.<br \/>\n\uc2a4\ucf00\uc904\ub7ec\ub97c\u00a0AndroidSchedulers.mainThread() \ub85c \ud574\uc8fc\uc9c0 \uc54a\uc73c\uba74 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud558\uac8c \ub429\ub2c8\ub2e4.<br \/>\n<em>Note:\uc561\ud2f0\ube44\ud2f0 \ube60\ub974\uac8c \uc2e4\ud589\ud588\uc744\ub54c\uc911\ubcf5 \uc2e4\ud589 \ub418\ub294 \ubb38\uc81c\ub3c4 debounce\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud788 \ud574\uacb0\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/em><br \/>\n\u00a0<\/p>\n<h3>RecyclerView, RxJava, DataBinding\ud65c\uc6a9\ud558\uc5ec \uac24\ub7ec\ub9ac \uc571 \ub9cc\ub4e4\uae30<\/h3>\n<p>\uc18c\uc2a4 :\u00a0<a href=\"https:\/\/github.com\/Charlezz\/GalleryApp\">https:\/\/github.com\/Charlezz\/GalleryApp<\/a><br \/>\n\u00a0<br \/>\nObservable\uc744 \ud65c\uc6a9\ud558\uc5ec \ube44\ub3d9\uae30 \uc774\ubca4\ud2b8\ub97c \ucc98\ub9ac\ud558\ub294 \uae30\ubcf8\uc801\uc778 \ud65c\uc6a9\ubc29\ubc95\uc5d0 \ub300\ud574\uc11c \uc54c\uc544\ubcf4\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<h4><\/h4>\n<p><strong>MainActivity.kt<\/strong><\/p>\n<pre>package com.charlezz.galleryapp.ui\r\nimport android.Manifest\r\nimport android.content.pm.PackageManager\r\nimport android.os.Bundle\r\nimport android.support.v4.app.ActivityCompat\r\nimport android.support.v7.app.AppCompatActivity\r\nimport com.charlezz.galleryapp.R\r\nimport io.reactivex.rxkotlin.Observables\r\nimport io.reactivex.rxkotlin.toObservable\r\nclass MainActivity : AppCompatActivity() {\r\n    val TAG = MainActivity::class.java.simpleName\r\n    val permissions = arrayOf(\r\n            Manifest.permission.READ_EXTERNAL_STORAGE\r\n    )\r\n    override fun onCreate(savedInstanceState: Bundle?) {\r\n        super.onCreate(savedInstanceState)\r\n        setContentView(R.layout.activity_main)\r\n        permissions.toObservable()\r\n                .filter {\r\n                    ActivityCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED\r\n                }\r\n                .toList()\r\n                .map {\r\n                    permissions.sortedArray()\r\n                }\r\n                .subscribe { permissionList: Array&lt;String&gt;?, _: Throwable? -&gt;\r\n                    permissionList?.let {\r\n                        ActivityCompat.requestPermissions(this, it, 0)\r\n                    }\r\n                }\r\n    }\r\n    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array&lt;out String&gt;, grantResults: IntArray) {\r\n        super.onRequestPermissionsResult(requestCode, permissions, grantResults)\r\n        Observables.zip(\r\n                permissions.toObservable(),\r\n                grantResults.toObservable())\r\n                .filter {\r\n                    it.second != PackageManager.PERMISSION_GRANTED\r\n                }.count()\r\n                .subscribe { permissionCount: Long?, t2: Throwable? -&gt;\r\n                    if (permissionCount == 0L) {\/\/zero means all permissions granted\r\n                        supportFragmentManager.beginTransaction()\r\n                                .replace(R.id.container, GalleryFragment.newInstance())\r\n                                .commit()\r\n                    } else {\r\n                        finish()\r\n                    }\r\n                }\r\n    }\r\n}<\/pre>\n<p>permission \uc744 \uc694\uccad\ud560 \ubc30\uc5f4(permissions)\uc744 \ubbf8\ub9ac \ub9cc\ub4ed\ub2c8\ub2e4. \uac24\ub7ec\ub9ac \uc571\uc758 \uacbd\uc6b0 READ_EXTERNAL_STORAGE\ub9cc \uc788\uc73c\uba74 \ub429\ub2c8\ub2e4.<br \/>\n\ud37c\ubbf8\uc158 \ubc30\uc5f4\uc744 \uc635\uc800\ubc84\ube14\ub85c \ubcc0\uacbd\ud558\uc5ec \ud604\uc7ac \ud5c8\uac00\ub418\uc9c0 \uc54a\uc740 \ud37c\ubbf8\uc158\uc744 \ucd94\ub824\ub0b8 \ub4a4 requestPermissions\uba54\uc18c\ub4dc\ub97c \uc774\uc6a9\ud558\uc5ec \uad8c\ud55c\uc744 \uc694\uccad\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4.<br \/>\n\uc694\uccad\ub41c \uad8c\ud55c\uc740 \uc0ac\uc6a9\uc790\ub85c \ud558\uc5ec\uae08 \ud5c8\uc6a9 \ub610\ub294 \uac70\ubd80\ub97c \ud560 \uc218 \uc788\uc73c\uba70 \uc804\ubd80 \ud5c8\uc6a9\ud560 \uc2dc \uc5d0\ub9cc \ub2e4\uc74c \ub3d9\uc791( Fragment \u00a0\ub744\uc6b0\uae30) \uc744 \uc218\ud589\ud558\ub3c4\ub85d \ud558\uace0, \ud55c\uac1c\ub77c\ub3c4 \uad8c\ud55c\uc744 \uac70\ubd80 \ud588\ub2e4\uba74 finish() \ub85c \uc571\uc744 \uc885\ub8cc\ud558\ub294 \ubaa8\uc2b5\uc785\ub2c8\ub2e4.<br \/>\n\u00a0<br \/>\n<strong>GalleryFragment.kt<\/strong><\/p>\n<pre class=\"\">class GalleryFragment : Fragment() {\r\n    val TAG = GalleryFragment::class.java.simpleName\r\n    companion object {\r\n        fun newInstance() = GalleryFragment()\r\n    }\r\n    lateinit var binding: FragmentGalleryBinding\r\n    val adapter = GalleryAdapter()\r\n    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {\r\n        binding = FragmentGalleryBinding.inflate(inflater, container, false)\r\n        return binding.root\r\n    }\r\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\r\n        super.onViewCreated(view, savedInstanceState)\r\n        binding.recyclerView.adapter = adapter\r\n        binding.recyclerView.layoutManager = GridLayoutManager(context, 3)\r\n    }\r\n    override fun onResume() {\r\n        super.onResume()\r\n        adapter.clearItems()\r\n        getItemsObservable()\r\n                .observeOn(AndroidSchedulers.mainThread())\r\n                .subscribe {\r\n                    adapter.addItem(it, true)\r\n                }\r\n    }\r\n    fun getItemsObservable(): Observable&lt;GalleryData&gt; {\r\n        val cursor = context?.contentResolver?.query(\r\n                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,\r\n                arrayOf(\r\n                        MediaStore.Images.Media.DISPLAY_NAME,\r\n                        MediaStore.Images.Media.DATA\r\n                ),\r\n                null,\r\n                null,\r\n                null)\r\n        cursor?.let {\r\n            return Observable.fromIterable(RxCursorIterable.from(cursor))\r\n                    .subscribeOn(Schedulers.io())\r\n                    .doAfterNext {\r\n                        if (it.isLast) {\r\n                            it.close()\r\n                        }\r\n                    }\r\n                    .map { c -&gt;\r\n                        val name = c.getString(c.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME))\r\n                        val path = c.getString(c.getColumnIndex(MediaStore.Images.Media.DATA))\r\n                        GalleryData(name, path)\r\n                    }\r\n        }\r\n        return Observable.empty&lt;GalleryData&gt;()\r\n    }\r\n}<\/pre>\n<p>getItemObservable\uba54\uc18c\ub4dc\ub97c \ubcf4\uba74 \ube44\ub3d9\uae30\uc801\uc73c\ub85c \uc774\ubbf8\uc9c0 \uc774\ub984\uacfc \uacbd\ub85c\ub97c GalleryData\ub77c\ub294 \ub370\uc774\ud130\ud074\ub798\uc2a4\uc5d0 \ubc1c\ud589\ud558\uac8c \ub418\uc5b4\uc788\ub2e4.<br \/>\nonResume()\uc5d0\uc11c\ub294 mainThread\uc2a4\ucf00\uc904\ub7ec\ub97c \uc774\uc6a9\ud558\uc5ec \uad6c\ub3c5\uc744 \ud558\uace0 \uc788\ub2e4. (View\ub97c \uac74\ub4dc\ub9b4\uc218 \uc788\ub294\uac74 \uc624\ub85c\uc9c0 \uba54\uc778\uc4f0\ub808\ub4dc \ubfd0!)<br \/>\n\u00a0<br \/>\n<strong>GalleryAdapter.kt<\/strong><\/p>\n<pre class=\"\">class GalleryAdapter : RecyclerView.Adapter&lt;GalleryAdapter.GalleryViewHolder&gt;() {\r\n    val items = ArrayList&lt;GalleryData&gt;()\r\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GalleryViewHolder {\r\n        val inflater = LayoutInflater.from(parent.context)\r\n        val binding = VhGalleryBinding.inflate(\r\n                inflater,\r\n                parent,\r\n                false)\r\n        return GalleryViewHolder(binding)\r\n    }\r\n    fun addItem(item: GalleryData, update: Boolean) {\r\n        items.add(item)\r\n        if (update) {\r\n            notifyItemChanged(items.lastIndex)\r\n        }\r\n    }\r\n    fun clearItems() {\r\n        items.clear()\r\n        notifyDataSetChanged()\r\n    }\r\n    override fun getItemCount(): Int {\r\n        return items.size\r\n    }\r\n    override fun onBindViewHolder(holder: GalleryViewHolder, position: Int) {\r\n        holder.binding.galleryData = items[position]\r\n        holder.binding.executePendingBindings()\r\n    }\r\n    class GalleryViewHolder(binding: VhGalleryBinding) : RecyclerView.ViewHolder(binding.root) {\r\n        val binding = binding\r\n    }\r\n}<\/pre>\n<p>addItem\uba54\uc18c\ub4dc\ub97c \ud1b5\ud558\uc5ec \ub9ac\uc2a4\ud2b8\uc5d0 \uc774\ubbf8\uc9c0\ub97c \ud558\ub098\uc529 \ucd94\uac00 \ud558\uace0 \uc788\ub2e4.<br \/>\nonBindViewHolder \uc5d0\uc11c\ub294 \ub370\uc774\ud130 \ubc14\uc778\ub529\uc744 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \ud65c\uc6a9\ud558\uc5ec \ub370\uc774\ud130\ub97c \uc8fc\uc785\ud558\uace0 \uc788\ub294 \ubaa8\uc2b5\uc774\ub2e4.<\/p>\n<hr \/>\n<p><a href=\"http:\/\/www.charlezz.com\/2018\/04\/13\/reactive-programing1-\ub9ac\uc561\ud2f0\ube0c-\ud504\ub85c\uadf8\ub798\ubc0d-\uac1c\ub150\uc7a1\uae30\/\">Reactive Programing(1) &#8211; \ub9ac\uc561\ud2f0\ube0c \ud504\ub85c\uadf8\ub798\ubc0d \uac1c\ub150\uc7a1\uae30<\/a><br \/>\n<a class=\"row-title\" href=\"http:\/\/www.charlezz.com\/2018\/04\/19\/reactive-programing2-reactive-operator\/\" aria-label=\"\u201cReactive Programing(2) \u2013 Reactive Operator\u201d (\ud3b8\uc9d1)\">Reactive Programing(2) \u2013 Reactive Operator<\/a><br \/>\n<a class=\"row-title\" href=\"http:\/\/www.charlezz.com\/2018\/04\/20\/reactive-programing3-reactive-operator\/\" aria-label=\"\u201cReactive Programing(3) \u2013 Reactive Operator\u201d (\ud3b8\uc9d1)\">Reactive Programing(3) \u2013 Reactive Operator<\/a><br \/>\n<a class=\"row-title\" href=\"http:\/\/www.charlezz.com\/2018\/05\/01\/reactive-programing4-scheduler\/\" aria-label=\"\u201cReactive Programing(4) \u2013 Scheduler\u201d (\ud3b8\uc9d1)\">Reactive Programing(4) \u2013 Scheduler<\/a><br \/>\nReactive Programing(5) \u2013 \uc548\ub4dc\ub85c\uc774\ub4dc\uc5d0\uc11c\uc758 RxJava \ud65c\uc6a9<\/p>\n<hr \/>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Reactive Programing(1) &#8211; \ub9ac\uc561\ud2f0\ube0c \ud504\ub85c\uadf8\ub798\ubc0d \uac1c\ub150\uc7a1\uae30 Reactive Programing(2) \u2013 Reactive Operator Reactive Programing(3) \u2013 Reactive Operator Reactive Programing(4) \u2013 Scheduler Reactive Programing(5) \u2013 \uc548\ub4dc\ub85c\uc774\ub4dc\uc5d0\uc11c\uc758 RxJava \ud65c\uc6a9 \uc548\ub4dc\ub85c\uc774\ub4dc\uc5d0\uc11c RxJava2 \uc0ac\uc6a9\ud558\uae30 \u00a0 \uc790\ubc14\ub294 \ud568\uc218\ud615 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \uc81c\ub300\ub85c \uc9c0\uc6d0\ud558\uc9c0 \ubabb\ud558\uace0 \uc788\uc73c\uba70, \uc5ec\uc804\ud788 Side Effect(\ubd80\uc218\ud6a8\uacfc)\ub97c \uc644\ubcbd\ud558\uac8c \uc81c\uac70\ud558\uc9c0 \ubabb\ud588\ub2e4. \uc774\ub7ec\ud55c \uc774\uc720\ub85c \uc548\ub4dc\ub85c\uc774\ub4dc\uc5d0\uc11c RxJava2\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"inline_featured_image":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[7],"tags":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/299"}],"collection":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=299"}],"version-history":[{"count":1,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/299\/revisions"}],"predecessor-version":[{"id":1381,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/299\/revisions\/1381"}],"wp:attachment":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=299"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=299"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=299"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}