// 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のほうが早かった