リファクタ
This commit is contained in:
parent
1b238d7db2
commit
03bb0c40ea
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinCommonCompilerArguments">
|
||||
<option name="coroutinesState" value="enable" />
|
||||
</component>
|
||||
</project>
|
|
@ -26,6 +26,12 @@ android {
|
|||
|
||||
}
|
||||
|
||||
kotlin {
|
||||
experimental {
|
||||
coroutines 'enable'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
|
@ -37,4 +43,7 @@ dependencies {
|
|||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
android:theme="@style/AppTheme"
|
||||
>
|
||||
|
||||
<activity android:name=".ActMain">
|
||||
<activity android:name=".ActList">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
|||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".ActApngView"/>
|
||||
<activity android:name=".ActViewer"/>
|
||||
|
||||
</application>
|
||||
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
package jp.juggler.apng.sample
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import jp.juggler.apng.ApngFrames
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class ActApngView : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
const val EXTRA_RES_ID = "res_id"
|
||||
const val EXTRA_CAPTION = "caption"
|
||||
|
||||
fun open(context: Context, resId:Int, caption:String){
|
||||
val intent =Intent( context, ActApngView::class.java)
|
||||
intent.putExtra(EXTRA_RES_ID,resId)
|
||||
intent.putExtra(EXTRA_CAPTION,caption)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var handler : Handler
|
||||
private lateinit var apngView : ApngView
|
||||
private lateinit var tvError : TextView
|
||||
|
||||
override fun onCreate(savedInstanceState : Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
this.handler = Handler()
|
||||
|
||||
val intent = this.intent
|
||||
val resId = intent.getIntExtra(EXTRA_RES_ID,0)
|
||||
this.title = intent.getStringExtra(EXTRA_CAPTION) ?: "?"
|
||||
|
||||
setContentView(R.layout.act_apng_view)
|
||||
this.apngView = findViewById(R.id.apngView)
|
||||
this.tvError = findViewById(R.id.tvError)
|
||||
|
||||
thread(start=true){
|
||||
try {
|
||||
this@ActApngView.resources.openRawResource(resId).use {
|
||||
val apngFrames = ApngFrames.parseApng(it, 1024)
|
||||
handler.post {
|
||||
if(isDestroyed) return@post
|
||||
apngView.visibility = View.VISIBLE
|
||||
tvError.visibility = View.GONE
|
||||
apngView.apngFrames = apngFrames
|
||||
}
|
||||
}
|
||||
}catch(ex:Throwable){
|
||||
ex.printStackTrace()
|
||||
Log.e(ActMain.TAG,"load error: ${ex.javaClass.simpleName} ${ex.message}")
|
||||
|
||||
val message = "%s %s".format( ex.javaClass.simpleName, ex.message)
|
||||
handler.post{
|
||||
if(isDestroyed) return@post
|
||||
apngView.visibility = View.GONE
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
apngView.apngFrames?.dispose()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
package jp.juggler.apng.sample
|
||||
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import jp.juggler.apng.ApngFrames
|
||||
import kotlinx.coroutines.experimental.*
|
||||
import kotlinx.coroutines.experimental.android.UI
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
class ActList : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
const val TAG = "ActList"
|
||||
}
|
||||
|
||||
class WeakRef<T : Any>(t : T) : WeakReference<T>(t) {
|
||||
operator fun invoke() : T? = get()
|
||||
}
|
||||
|
||||
fun <T : Any> ref(t : T) = WeakRef(t)
|
||||
|
||||
class ListItem(val id : Int, val caption : String)
|
||||
|
||||
private lateinit var listView : ListView
|
||||
private lateinit var listAdapter : MyAdapter
|
||||
|
||||
override fun onCreate(savedInstanceState : Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.act_list)
|
||||
this.listView = findViewById(R.id.listView)
|
||||
listAdapter = MyAdapter()
|
||||
listView.adapter = listAdapter
|
||||
listView.onItemClickListener = listAdapter
|
||||
|
||||
launch(UI) {
|
||||
val list = async(CommonPool) {
|
||||
// RawリソースのIDと名前の一覧
|
||||
R.raw::class.java.fields
|
||||
.mapNotNull {
|
||||
val id = it.get(null) as? Int
|
||||
if(id == null) {
|
||||
null
|
||||
} else {
|
||||
ListItem(
|
||||
id,
|
||||
resources.getResourceName(id).replaceFirst(""".+/""".toRegex(), "")
|
||||
)
|
||||
}
|
||||
}
|
||||
.toMutableList()
|
||||
.let { list ->
|
||||
list.sortBy { item -> item.caption }
|
||||
list
|
||||
}
|
||||
|
||||
}.await()
|
||||
|
||||
if(isDestroyed) return@launch
|
||||
|
||||
listAdapter.list.addAll(list)
|
||||
listAdapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
inner class MyAdapter : BaseAdapter(), AdapterView.OnItemClickListener {
|
||||
|
||||
val list = ArrayList<ListItem>()
|
||||
|
||||
override fun getCount() : Int {
|
||||
return list.size
|
||||
}
|
||||
|
||||
override fun getItem(position : Int) : Any {
|
||||
return list[position]
|
||||
}
|
||||
|
||||
override fun getItemId(position : Int) : Long {
|
||||
return list[position].id.toLong()
|
||||
}
|
||||
|
||||
override fun getView(
|
||||
position : Int,
|
||||
viewArg : View?,
|
||||
parent : ViewGroup?
|
||||
) : View {
|
||||
val view : View
|
||||
val holder : MyViewHolder
|
||||
if(viewArg == null) {
|
||||
view = layoutInflater.inflate(R.layout.lv_item, parent, false)
|
||||
holder = MyViewHolder(view, ref(this@ActList))
|
||||
view.tag = holder
|
||||
} else {
|
||||
view = viewArg
|
||||
holder = view.tag as MyViewHolder
|
||||
}
|
||||
holder.bind(list[position])
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onItemClick(
|
||||
parent : AdapterView<*>?,
|
||||
view : View?,
|
||||
position : Int,
|
||||
id : Long
|
||||
) {
|
||||
val item = list[position]
|
||||
ActViewer.open(this@ActList, item.id, item.caption)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MyViewHolder(
|
||||
viewRoot : View,
|
||||
private val activity : WeakRef<ActList>
|
||||
) {
|
||||
|
||||
private val tvCaption : TextView = viewRoot.findViewById(R.id.tvCaption)
|
||||
private val apngView : ApngView = viewRoot.findViewById(R.id.apngView)
|
||||
|
||||
private var lastId : Int = 0
|
||||
private var lastJob : Job? = null
|
||||
|
||||
fun bind(listItem : ListItem) {
|
||||
tvCaption.text = listItem.caption
|
||||
|
||||
val resId = listItem.id
|
||||
if(lastId != resId) {
|
||||
lastId = resId
|
||||
apngView.apngFrames?.dispose()
|
||||
apngView.apngFrames = null
|
||||
Log.d(TAG, "loading start: id=$resId")
|
||||
launch(UI) {
|
||||
try {
|
||||
if(activity()?.isDestroyed != false) return@launch
|
||||
|
||||
lastJob?.cancelAndJoin()
|
||||
|
||||
val job = async(CommonPool) {
|
||||
activity()?.resources?.openRawResource(resId)?.use { inStream ->
|
||||
ApngFrames.parseApng(inStream, 128)
|
||||
}
|
||||
}
|
||||
lastJob = job
|
||||
val apngFrames = job.await()
|
||||
|
||||
if(activity()?.isDestroyed == false
|
||||
&& lastId == resId
|
||||
&& apngFrames != null
|
||||
) {
|
||||
Log.d(TAG, "loading complete: resId=$resId")
|
||||
apngView.apngFrames = apngFrames
|
||||
} else {
|
||||
apngFrames?.dispose()
|
||||
}
|
||||
} catch(ex : Throwable) {
|
||||
ex.printStackTrace()
|
||||
Log.e(TAG, "load error: ${ex.javaClass.simpleName} ${ex.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
package jp.juggler.apng.sample
|
||||
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import jp.juggler.apng.ApngFrames
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class ActMain : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
const val TAG = "ActMain"
|
||||
}
|
||||
|
||||
private lateinit var listView : ListView
|
||||
private lateinit var listAdapter: MyAdapter
|
||||
private lateinit var handler: Handler
|
||||
override fun onCreate(savedInstanceState : Bundle?) {
|
||||
handler = Handler()
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.act_main)
|
||||
this.listView = findViewById(R.id.listView)
|
||||
listAdapter = MyAdapter()
|
||||
listView.adapter = listAdapter
|
||||
listView.onItemClickListener = listAdapter
|
||||
|
||||
thread(start=true){
|
||||
|
||||
// RawリソースのIDと名前の一覧
|
||||
val list = ArrayList<ListItem>()
|
||||
R.raw::class.java.fields
|
||||
.mapNotNull { it.get(null) as? Int}
|
||||
.forEach { list.add(
|
||||
ListItem(
|
||||
it,
|
||||
resources.getResourceName(it).replaceFirst(""".+/""".toRegex(), "")
|
||||
)
|
||||
)}
|
||||
|
||||
list.sortBy { it.caption }
|
||||
|
||||
handler.post{
|
||||
if(isDestroyed) return@post
|
||||
listAdapter.list.addAll(list)
|
||||
listAdapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ListItem(val id:Int,val caption:String)
|
||||
|
||||
inner class MyAdapter :BaseAdapter(), AdapterView.OnItemClickListener {
|
||||
|
||||
val list = ArrayList<ListItem>()
|
||||
|
||||
override fun getCount() : Int {
|
||||
return list.size
|
||||
}
|
||||
|
||||
override fun getItem(position : Int) : Any {
|
||||
return list[position]
|
||||
}
|
||||
override fun getItemId(position : Int) : Long {
|
||||
return list[position].id.toLong()
|
||||
}
|
||||
|
||||
override fun getView(
|
||||
position : Int,
|
||||
viewArg : View?,
|
||||
parent : ViewGroup?
|
||||
) : View {
|
||||
val view:View
|
||||
val holder: MyViewHolder
|
||||
if( viewArg == null ){
|
||||
view = layoutInflater.inflate(R.layout.lv_main,parent,false)
|
||||
holder = MyViewHolder(view)
|
||||
view.tag = holder
|
||||
}else{
|
||||
view = viewArg
|
||||
holder = view.tag as MyViewHolder
|
||||
}
|
||||
holder.bind( list[position])
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onItemClick(
|
||||
parent : AdapterView<*>?,
|
||||
view : View?,
|
||||
position : Int,
|
||||
id : Long
|
||||
) {
|
||||
val item = list[position]
|
||||
ActApngView.open(this@ActMain, item.id, item.caption)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inner class MyViewHolder(viewRoot:View){
|
||||
private val tvCaption : TextView = viewRoot.findViewById(R.id.tvCaption)
|
||||
private val apngView: ApngView = viewRoot.findViewById(R.id.apngView)
|
||||
private var lastId : Int = -1
|
||||
fun bind(listItem : ListItem) {
|
||||
tvCaption.text = listItem.caption
|
||||
|
||||
val resId = listItem.id
|
||||
if( lastId != resId){
|
||||
Log.d(TAG,"loading start: resId=$resId lastId=$lastId")
|
||||
lastId =resId
|
||||
apngView.apngFrames?.dispose()
|
||||
apngView.apngFrames=null
|
||||
thread (start=true){
|
||||
try {
|
||||
resources.openRawResource(resId).use { inStream->
|
||||
val apngFrames = ApngFrames.parseApng(inStream, 128)
|
||||
handler.post( {
|
||||
if(isDestroyed) return@post
|
||||
if( lastId != resId) {
|
||||
Log.d(TAG,"loading cancelled: resId=$resId,lastId=$lastId")
|
||||
}else{
|
||||
Log.d(TAG,"loading complete: resId=$resId")
|
||||
apngView.apngFrames = apngFrames
|
||||
}
|
||||
})
|
||||
}
|
||||
}catch(ex:Throwable){
|
||||
ex.printStackTrace()
|
||||
Log.e(TAG,"load error: ${ex.javaClass.simpleName} ${ex.message}")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package jp.juggler.apng.sample
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import jp.juggler.apng.ApngFrames
|
||||
import kotlinx.coroutines.experimental.CommonPool
|
||||
import kotlinx.coroutines.experimental.android.UI
|
||||
import kotlinx.coroutines.experimental.async
|
||||
import kotlinx.coroutines.experimental.launch
|
||||
|
||||
class ActViewer : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
const val EXTRA_RES_ID = "res_id"
|
||||
const val EXTRA_CAPTION = "caption"
|
||||
|
||||
fun open(context : Context, resId : Int, caption : String) {
|
||||
val intent = Intent(context, ActViewer::class.java)
|
||||
intent.putExtra(EXTRA_RES_ID, resId)
|
||||
intent.putExtra(EXTRA_CAPTION, caption)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var apngView : ApngView
|
||||
private lateinit var tvError : TextView
|
||||
|
||||
override fun onCreate(savedInstanceState : Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val intent = this.intent
|
||||
val resId = intent.getIntExtra(EXTRA_RES_ID, 0)
|
||||
this.title = intent.getStringExtra(EXTRA_CAPTION) ?: "?"
|
||||
|
||||
setContentView(R.layout.act_apng_view)
|
||||
this.apngView = findViewById(R.id.apngView)
|
||||
this.tvError = findViewById(R.id.tvError)
|
||||
|
||||
launch(UI) {
|
||||
try {
|
||||
if(isDestroyed) return@launch
|
||||
|
||||
val apngFrames = async(CommonPool) {
|
||||
resources.openRawResource(resId).use {
|
||||
ApngFrames.parseApng(it, 1024)
|
||||
}
|
||||
}.await()
|
||||
|
||||
if(isDestroyed) {
|
||||
apngFrames.dispose()
|
||||
} else {
|
||||
apngView.visibility = View.VISIBLE
|
||||
tvError.visibility = View.GONE
|
||||
apngView.apngFrames = apngFrames
|
||||
}
|
||||
} catch(ex : Throwable) {
|
||||
ex.printStackTrace()
|
||||
Log.e(ActList.TAG, "load error: ${ex.javaClass.simpleName} ${ex.message}")
|
||||
|
||||
val message = "%s %s".format(ex.javaClass.simpleName, ex.message)
|
||||
if(! isDestroyed) {
|
||||
apngView.visibility = View.GONE
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
apngView.apngFrames?.dispose()
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
|
||||
ext.kotlin_version = '1.2.20'
|
||||
ext.kotlin_version = '1.2.21'
|
||||
ext.kotlin_coroutines_version = '0.21.2'
|
||||
ext.anko_version='0.10.4'
|
||||
|
||||
repositories {
|
||||
|
@ -13,11 +12,7 @@ buildscript {
|
|||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
||||
classpath 'com.google.gms:google-services:3.0.0'
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue