coroutine(kotlin)を使って簡単なAndroidアプリを作ってみた

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
  ext.kotlin_version = '1.1.0'
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:2.3.0'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
  }
}


allprojects {
  repositories {
    jcenter()
  }
}

task clean(type: Delete) {
  delete rootProject.buildDir
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
  compileSdkVersion 25
  buildToolsVersion "25.0.2"
  defaultConfig {
    applicationId "jp.co.no.coroutine_application"
    minSdkVersion 15
    targetSdkVersion 25
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  }
  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
  })
  compile 'com.android.support:appcompat-v7:25.2.0'
  compile 'com.android.support.constraint:constraint-layout:1.0.2'
  //kotlin coroutines
  compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.12'
  testCompile 'junit:junit:4.12'
}
<?xml version="1.0" encoding="utf-8"?>
<manifest package="jp.co.no.coroutine_application"
		  xmlns:android="http://schemas.android.com/apk/res/android">
	<uses-permission android:name="android.permission.INTERNET"/>
	<application
		android:allowBackup="true"
		android:icon="@mipmap/ic_launcher"
		android:label="@string/app_name"
		android:roundIcon="@mipmap/ic_launcher_round"
		android:supportsRtl="true"
		android:theme="@style/AppTheme">
		<activity android:name=".MainActivity">
			<intent-filter>
				<action android:name="android.intent.action.MAIN"/>

				<category android:name="android.intent.category.LAUNCHER"/>
			</intent-filter>
		</activity>
	</application>

</manifest>

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
	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="match_parent"
	tools:context="jp.co.no.coroutine_application.MainActivity">

	<TextView
		android:id="@+id/text"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Hello World!"
		app:layout_constraintBottom_toBottomOf="parent"
		app:layout_constraintLeft_toLeftOf="parent"
		app:layout_constraintRight_toRightOf="parent"
		app:layout_constraintTop_toTopOf="parent"/>

</android.support.constraint.ConstraintLayout>

yahooのトップページのHTMLを表示するだけのアプリを作ってみます

package jp.co.no.coroutine_application

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.TextView
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.runBlocking
import java.net.URL

class MainActivity : AppCompatActivity() {

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		//start
		val deferred = asyncLoad()
		setContentView(R.layout.activity_main)
		val textView = findViewById(R.id.text) as TextView
		runBlocking {
			//await
			textView.text = deferred.await()
		}
	}

	fun asyncLoad() = async(CommonPool) {
		val url = URL("http://www.yahoo.co.jp/")
		url.openConnection().apply {
			connectTimeout = 3 * 1000
			readTimeout = 3 * 1000
		}
				.getInputStream()
				.bufferedReader()
				.readText()
	}
}

Threadで似たものは作れますが

class AsyncThread<out Result>(start: Boolean = true, val runnable: () -> Result) : Thread() {

	init {
		if (start) start()
	}

	private var result: Result? = null
	override fun run() {
		result = runnable.invoke()
	}

	fun await(): Result? {
		join()
		return result
	}
}

package jp.co.no.coroutine_application

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.TextView
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.runBlocking
import java.net.URL

class MainActivity : AppCompatActivity() {

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		setContentView(R.layout.activity_main)
		val textView = findViewById(R.id.text) as TextView
		val deferred2 = aLotOf()
		runBlocking {
			textView.text = deferred2.await()
		}
		val deferred3 = aLotOf2()
		textView.text = deferred3.await()
	}

	private fun aLotOf2() = AsyncThread {
		val jobs = List(10_000) {

			AsyncThread {
				Thread.sleep(1000)
				"."
			}
		}
		jobs.map { it.await() }.reduce { str1, str2 -> str1 + str2 }
	}

	fun asyncLoad() = async(CommonPool) {
		val url = URL("http://www.yahoo.co.jp/")
		url.openConnection().apply {
			connectTimeout = 3 * 1000
			readTimeout = 3 * 1000
		}
				.getInputStream()
				.bufferedReader()
				.readText()
	}

	fun aLotOf() = async(CommonPool) {
		val jobs = List(10_000) {

			async(CommonPool) {
				delay(1000L)
				"."
			}
		}
		jobs.map { it.await() }.reduce { str1, str2 -> str1 + str2 }
	}
}

class AsyncThread<out Result>(start: Boolean = true, val runnable: () -> Result) : Thread() {

	init {
		if (start) start()
	}

	private var result: Result? = null
	override fun run() {
		result = runnable.invoke()
	}

	fun await(): Result? {
		join()
		return result
	}
}

こんな感じで作ってみるとcoroutineのほうが早かった

スポンサーリンク

シェアする

フォローする

スポンサーリンク