{"id":553,"date":"2024-08-20T12:11:00","date_gmt":"2024-08-20T03:11:00","guid":{"rendered":"https:\/\/txn.myds.me\/blog\/?p=553"},"modified":"2024-08-20T12:11:00","modified_gmt":"2024-08-20T03:11:00","slug":"android-%e3%81%a7%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%a8%e9%80%9a%e4%bf%a1%e3%81%99%e3%82%8b-livedata%e7%b7%a8","status":"publish","type":"post","link":"https:\/\/blog.txn.red\/?p=553","title":{"rendered":"Android \u3067\u30b5\u30fc\u30d3\u30b9\u3068\u901a\u4fe1\u3059\u308b-LiveData\u7de8"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">\u305d\u306e 2 \u4eca\u5ea6\u306f LiveData \u3092\u4f7f\u3063\u3066\u307f\u307e\u3059\u3002<\/p>\n\n\n\n\n\n<p class=\"wp-block-paragraph\">LiveData \u3092\u4f7f\u3046\u306a\u3089\u3053\u3093\u306a\u611f\u3058<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-Kotlin\" data-file=\"MainActivity.kt\" data-lang=\"Kotlin\" data-line=\"44, 51, 58-63\"><code>package red.txn.service_livedata\n\nimport android.content.ComponentName\nimport android.content.Context\nimport android.content.Intent\nimport android.content.ServiceConnection\nimport android.os.Bundle\nimport android.os.IBinder\nimport android.util.Log\nimport androidx.activity.ComponentActivity\nimport androidx.activity.compose.setContent\nimport androidx.activity.enableEdgeToEdge\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.tooling.preview.Preview\nimport red.txn.service_livedata.ui.theme.ServicelivedataTheme\n\nclass MainActivity : ComponentActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        enableEdgeToEdge()\n        setContent {\n            ServicelivedataTheme {\n                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -&gt;\n                    Greeting(\n                        name = &quot;Android&quot;,\n                        modifier = Modifier.padding(innerPadding)\n                    )\n                }\n            }\n        }\n\n        \/\/ launch service\n        Intent(this, LiveDataService::class.java).also { intent -&gt;\n            bindService(intent, connection, Context.BIND_AUTO_CREATE)\n        }\n    }\n\n    private var bound = false\n    private lateinit var liveDataService: LiveDataService\n\n    private val connection = object : ServiceConnection {\n        override fun onServiceConnected(name: ComponentName?, service: IBinder) {\n            val binder = service as LiveDataService.MyBinder\n            liveDataService = binder.getService()\n            bound = true\n            observeData()\n        }\n        override fun onServiceDisconnected(name: ComponentName?) {\n            bound = false\n        }\n    }\n\n    fun observeData() {\n        liveDataService.BUS.observe(this) { newData -&gt;\n            Log.d(&quot;AAA&quot;, &quot;Activity:&quot; + newData.toString())\n        }\n    }\n}\n\n\n\/\/***\n\/\/*** Composable functions\n\/\/***\n@Composable\nfun Greeting(name: String, modifier: Modifier = Modifier) {\n    Text(\n        text = &quot;Hello $name!&quot;,\n        modifier = modifier\n    )\n}\n\n@Preview(showBackground = true)\n@Composable\nfun GreetingPreview() {\n    ServicelivedataTheme {\n        Greeting(&quot;Android&quot;)\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">bindService() \u3067\u30b5\u30fc\u30d3\u30b9\u8d77\u52d5\u3092\u3057\u3066\u3044\u308b\u306e\u3067\u5c11\u3057\u69d8\u5b50\u304c\u7570\u306a\u308b\u304c\u3001\u30d0\u30a4\u30f3\u30c9\u3057\u305f\u3068\u304d observeData() \u3067\u76e3\u8996\u3057\u3066\u3044\u308b\u3002\u3068\u3063\u3066\u3082\u7c21\u5358<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-Kotlin\" data-file=\"LiveDataService.kt\" data-lang=\"Kotlin\" data-line=\"44\"><code>package red.txn.service_livedata\n\nimport android.app.Service\nimport android.content.Intent\nimport android.os.Binder\nimport android.os.IBinder\nimport android.util.Log\nimport androidx.lifecycle.MutableLiveData\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\n\nclass LiveDataService : Service() {\n    companion object {\n        const val TAG = &quot;LiveDataService&quot;\n    }\n\n    val BUS = MutableLiveData&lt;String&gt;()\n\n    override fun onBind(intent: Intent): IBinder {\n        Log.d(TAG, &quot;serviee onBind()&quot;)\n        Thread {\n            for (i in 1..2) {\n                Thread.sleep(2000)\n                updateData(&quot;\u30c7\u30fc\u30bf$i&quot;)\n                Log.d(TAG, &quot;\u30c7\u30fc\u30bf$i&quot;)\n            }\n        }.start()\n\n        val scope = CoroutineScope(Dispatchers.IO)\n        scope.launch {\n            for (i in 1..2) {\n                Thread.sleep(2000)\n                updateData(&quot;\u30c7\u30fc\u30bf2$i&quot;)\n                Log.d(TAG, &quot;\u30c7\u30fc\u30bf2$i&quot;)\n            }\n        }\n        return MyBinder()\n    }\n    inner class MyBinder: Binder() {\n        fun getService(): LiveDataService = this@LiveDataService\n    }\n\n    private fun updateData(newData: String) {\n        BUS.postValue(newData)\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">AndroidManifest.xml \u306f\u751f\u6210\u3055\u308c\u305f\u3082\u306e\u306a\u306e\u3067\u7701\u7565\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">startService\uff08\uff09 \u3067\u30b5\u30fc\u30d3\u30b9\u8d77\u52d5\u3057\u305f\u3044\u5834\u5408\u306f\u3001\u3053\u3093\u306a\u3075\u3046\u306b\u306a\u3063\u305f\u3002<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-Kotlin\" data-file=\"MainActivity.kt\" data-lang=\"Kotlin\" data-line=\"39, 41-43\"><code>package red.txn.service_livedata\n\nimport android.content.ComponentName\nimport android.content.Context\nimport android.content.Intent\nimport android.content.ServiceConnection\nimport android.os.Bundle\nimport android.os.IBinder\nimport android.util.Log\nimport androidx.activity.ComponentActivity\nimport androidx.activity.compose.setContent\nimport androidx.activity.enableEdgeToEdge\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.tooling.preview.Preview\nimport red.txn.service_livedata.ui.theme.ServicelivedataTheme\n\nclass MainActivity : ComponentActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        enableEdgeToEdge()\n        setContent {\n            ServicelivedataTheme {\n                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -&gt;\n                    Greeting(\n                        name = &quot;Android&quot;,\n                        modifier = Modifier.padding(innerPadding)\n                    )\n                }\n            }\n        }\n\n        \/\/ launch service\n        Intent(this, LiveDataService::class.java).also { intent -&gt;\n            startService(intent)\n        }\n        LiveDataService.BUS.observe(this) {\n            Log.d(&quot;BUS change:&quot;, &quot;Activity:&quot; + it.toString())\n        }\n    }\n}\n\n\n\/\/***\n\/\/*** Composable functions\n\/\/***\n@Composable\nfun Greeting(name: String, modifier: Modifier = Modifier) {\n    Text(\n        text = &quot;Hello $name!&quot;,\n        modifier = modifier\n    )\n}\n\n@Preview(showBackground = true)\n@Composable\nfun GreetingPreview() {\n    ServicelivedataTheme {\n        Greeting(&quot;Android&quot;)\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">\u30b5\u30fc\u30d3\u30b9\u306e\u65b9\u3067\u306f LiveData \u3092 companion object \u306b\u5165\u308c\u3066\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306a\u3057\u3067\u3082\u53d6\u5f97\u3067\u304d\u308b\u3088\u3046\u306b\u3057\u3066\u3044\u308b\u3002<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-Kotlin\" data-file=\"LiveDataService.kt\" data-lang=\"Kotlin\" data-line=\"29\"><code>package red.txn.service_livedata\n\nimport android.app.Service\nimport android.content.Intent\nimport android.os.Binder\nimport android.os.IBinder\nimport android.util.Log\nimport androidx.lifecycle.MutableLiveData\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\n\nclass LiveDataService : Service() {\n    companion object {\n        const val TAG = &quot;LiveDataService&quot;\n        val BUS = MutableLiveData&lt;String&gt;()\n    }\n\n    override fun onBind(intent: Intent): IBinder? {\n        return null\n    }\n\n    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {\n        super.onStartCommand(intent, flags, startId)\n\n        Thread {\n            for (i in 1..2) {\n                Thread.sleep(2000)\n                BUS.postValue(&quot;newData: $i&quot;)\n            }\n        }\n\n        return START_STICKY\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Gemini \u3092\u4f7f\u3063\u3066\u307f\u3066\u3044\u308b\u304c\u3001\u524d\u306e\u6587\u8108\u304b\u3089\u306e\u7d9a\u304d\u306e\u8cea\u554f\u3057\u305f\u3089\u6d41\u308c\u3092\u3076\u3063\u305f\u5207\u3063\u3066\u65b0\u3057\u3044\u8a71\u984c\u306e\u3088\u3046\u306b\u56de\u7b54\u3059\u308b\u306e\u3084\u3081\u3066\u307b\u3057\u3044\u3002Claude \u306e\u307b\u3046\u304c\u305d\u306e\u8fba\u697d\u304b\u3082\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u305d\u306e 2 \u4eca\u5ea6\u306f LiveData \u3092\u4f7f\u3063\u3066\u307f\u307e\u3059\u3002 LiveData \u3092\u4f7f\u3046\u306a\u3089\u3053\u3093\u306a\u611f\u3058 bindService() \u3067\u30b5\u30fc\u30d3\u30b9\u8d77\u52d5\u3092\u3057\u3066\u3044\u308b\u306e\u3067\u5c11\u3057\u69d8\u5b50\u304c\u7570\u306a\u308b\u304c\u3001\u30d0\u30a4\u30f3\u30c9\u3057\u305f\u3068\u304d observeData() \u3067\u76e3 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":1,"footnotes":""},"categories":[9],"tags":[4],"class_list":["post-553","post","type-post","status-publish","format-standard","hentry","category-dev","tag-android"],"_links":{"self":[{"href":"https:\/\/blog.txn.red\/index.php?rest_route=\/wp\/v2\/posts\/553","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.txn.red\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.txn.red\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.txn.red\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.txn.red\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=553"}],"version-history":[{"count":0,"href":"https:\/\/blog.txn.red\/index.php?rest_route=\/wp\/v2\/posts\/553\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.txn.red\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=553"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.txn.red\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=553"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.txn.red\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=553"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}