{"action":"opened","issue":{"url":"https://api.github.com/repos/Mr-wangyong/ImageFrame/issues/13","repository_url":"https://api.github.com/repos/Mr-wangyong/ImageFrame","labels_url":"https://api.github.com/repos/Mr-wangyong/ImageFrame/issues/13/labels{/name}","comments_url":"https://api.github.com/repos/Mr-wangyong/ImageFrame/issues/13/comments","events_url":"https://api.github.com/repos/Mr-wangyong/ImageFrame/issues/13/events","html_url":"https://github.com/Mr-wangyong/ImageFrame/issues/13","id":296266125,"number":13,"title":"另外一种实现方式","user":{"login":"nobeginning","id":4122891,"avatar_url":"https://avatars3.githubusercontent.com/u/4122891?v=4","gravatar_id":"","url":"https://api.github.com/users/nobeginning","html_url":"https://github.com/nobeginning","followers_url":"https://api.github.com/users/nobeginning/followers","following_url":"https://api.github.com/users/nobeginning/following{/other_user}","gists_url":"https://api.github.com/users/nobeginning/gists{/gist_id}","starred_url":"https://api.github.com/users/nobeginning/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nobeginning/subscriptions","organizations_url":"https://api.github.com/users/nobeginning/orgs","repos_url":"https://api.github.com/users/nobeginning/repos","events_url":"https://api.github.com/users/nobeginning/events{/privacy}","received_events_url":"https://api.github.com/users/nobeginning/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-02-12T04:52:11Z","updated_at":"2018-02-12T04:52:11Z","closed_at":null,"author_association":"NONE","body":"用Kotlin实现的另外一种方式的思路。看一下是否有参考价值\r\n\r\n用法：\r\n```\r\nprotected void onCreate(Bundle savedInstanceState) {\r\n        super.onCreate(savedInstanceState);\r\n        setContentView(R.layout.activity_anim);\r\n\r\n        View imageView = findViewById(R.id.imageView);\r\n        List<Integer> resources = new ArrayList<>(32);\r\n        Resources res = getResources();\r\n        final String packageName = getPackageName();\r\n        for (int i=1; i<=210; i++){\r\n                String resName = \"gift_\" + i;\r\n                int imageResId = res.getIdentifier(resName, \"drawable\", packageName);\r\n                resources.add(imageResId);\r\n        }\r\n        controller = FrameAnim.Companion.create()\r\n                .target(imageView)    //target支持任意View\r\n                .resources(resources)\r\n                .duration(16)\r\n                .controller();\r\n        controller.start();\r\n\r\n        imageView.setOnClickListener(new View.OnClickListener() {\r\n            @Override\r\n            public void onClick(View v) {\r\n                if (controller == null) {\r\n                    return;\r\n                }\r\n                if (controller.isPaused()) {\r\n                    controller.resume();\r\n                } else {\r\n                    controller.pause();\r\n                }\r\n            }\r\n        });\r\n}\r\n```\r\n\r\n主要功能类如下：\r\n```\r\nimport android.graphics.drawable.BitmapDrawable\r\nimport android.os.Handler\r\nimport android.os.HandlerThread\r\nimport android.os.Looper\r\nimport android.support.v4.view.ViewCompat\r\nimport android.util.Log\r\nimport android.view.View\r\nimport com.mrwang.imageframe.BitmapLoadUtils\r\nimport com.mrwang.imageframe.ImageCache\r\nimport java.lang.ref.SoftReference\r\n\r\n/**\r\n * Created by young on 2018/2/8.\r\n */\r\n\r\n\r\nclass FrameAnim {\r\n\r\n    companion object {\r\n        fun create(): FrameAnim {\r\n            return FrameAnim()\r\n        }\r\n    }\r\n\r\n    interface AnimEndCallBack{\r\n        fun onAnimEnd()\r\n    }\r\n\r\n    interface AnimLoopedCallBack{\r\n        fun onAnimLooped(loopedCount:Int)\r\n    }\r\n\r\n    /**\r\n     * 遥控器\r\n     */\r\n    interface Controller {\r\n        fun start()\r\n        fun isPaused(): Boolean\r\n        fun pause()\r\n        fun resume()\r\n        fun destroy()\r\n    }\r\n\r\n    private inner class ControllerImpl(val ext: FrameAnim) : Controller {\r\n        override fun start() {\r\n            ext.start()\r\n        }\r\n\r\n        override fun destroy() {\r\n            ext.destroy()\r\n        }\r\n\r\n        override fun isPaused(): Boolean {\r\n            return ext.paused\r\n        }\r\n\r\n        override fun pause() {\r\n            ext.pause()\r\n        }\r\n\r\n        override fun resume() {\r\n            ext.resume()\r\n        }\r\n    }\r\n\r\n    private val TAG = javaClass.simpleName\r\n\r\n    private var target: View? = null\r\n    private var list: List<Int>? = null\r\n    private var duration: Long = 300\r\n    private var index = 0\r\n    private val decodeThread = DecodeThread()\r\n    private var decodeHandler: Handler? = null\r\n    private val uiHandler = Handler(Looper.getMainLooper())\r\n    private var bitmapDrawable: BitmapDrawable? = null\r\n    private var isInitLoad = true\r\n    private var loop = true\r\n    private var loopedCount = 0\r\n    private var paused = false\r\n    private var destroyed = false\r\n    private val controller: Controller = ControllerImpl(this)\r\n    private var animEndCallBack:AnimEndCallBack? = null\r\n    private var animLoopedCallBack:AnimLoopedCallBack? = null\r\n\r\n    private val autoDestroy:IAutoDestroy = object : IAutoDestroy {\r\n        override fun autoDestroy() {\r\n            destroy()\r\n        }\r\n    }\r\n\r\n    fun target(target: View): FrameAnim {\r\n        this.target = target\r\n        return this\r\n    }\r\n\r\n    fun resources(list: List<Int>): FrameAnim {\r\n        this.list = list\r\n        return this\r\n    }\r\n\r\n    fun duration(duration: Long): FrameAnim {\r\n        this.duration = duration\r\n        return this\r\n    }\r\n\r\n    fun loop(lp: Boolean): FrameAnim {\r\n        this.loop = lp\r\n        return this\r\n    }\r\n\r\n    fun callBackForAnimEnd(endCallBack: AnimEndCallBack): FrameAnim {\r\n        this.animEndCallBack = endCallBack\r\n        return this\r\n    }\r\n\r\n    fun callBackForAnimLooped(loopedCallBack: AnimLoopedCallBack): FrameAnim {\r\n        this.animLoopedCallBack = loopedCallBack\r\n        return this\r\n    }\r\n\r\n    fun controller():Controller{\r\n        return controller\r\n    }\r\n\r\n    fun start(): Controller {\r\n        if (target == null) {\r\n            Log.w(TAG, \"The target is Null\")\r\n            throw IllegalArgumentException(\"The target must not be Null\")\r\n        }\r\n        if (list == null || list!!.isEmpty()) {\r\n            Log.w(TAG, \"The resources is Empty\")\r\n            throw IllegalArgumentException(\"The resources must not be Null or Empty\")\r\n        }\r\n        val ctx = target!!.context\r\n        ctx.registerAutoDestroy(autoDestroy)\r\n        if (decodeHandler!=null){\r\n            Log.e(TAG, \"Task already started\")\r\n            return controller\r\n        }\r\n        if (paused) {\r\n            Log.e(TAG, \"Task is paused, Please use resume() to continue\")\r\n            return controller\r\n        }\r\n        decodeThread.start()\r\n        if (decodeHandler == null) {\r\n            decodeHandler = Handler(decodeThread.looper)\r\n        }\r\n        load()\r\n        return controller\r\n    }\r\n\r\n    private fun pause() {\r\n        if (decodeHandler == null) {\r\n            throw IllegalStateException(\"Have u forgot to invoke the ``fun start()``\")\r\n        }\r\n        paused = true\r\n        decodeHandler!!.removeCallbacksAndMessages(null)\r\n        uiHandler.removeCallbacksAndMessages(null)\r\n    }\r\n\r\n    private fun resume() {\r\n        if (decodeHandler == null) {\r\n            throw IllegalStateException(\"Have u forgot to invoke the ``fun start()``\")\r\n        }\r\n        paused = false\r\n        load()\r\n    }\r\n\r\n    fun destroy() {\r\n        if (destroyed){\r\n            return\r\n        }\r\n        destroyed = true\r\n        decodeThread.quit()\r\n        uiHandler.removeCallbacks(uiCallBack)\r\n        println(\"Component has destroyed\")\r\n    }\r\n\r\n    private var uiCallBack: Runnable? = null\r\n    private val imageCache = ImageCache()\r\n    private fun load() {\r\n        val resources = list!!\r\n        if (index >= resources.size && loop) {\r\n            index = 0\r\n            loopedCount++\r\n            animLoopedCallBack?.onAnimLooped(loopedCount)\r\n        } else if (index >= resources.size && !loop) {\r\n            Log.d(TAG, \"The End\")\r\n            println(\"The End\")\r\n            animEndCallBack?.onAnimEnd()\r\n            return\r\n        }\r\n\r\n        if (bitmapDrawable != null) {\r\n            imageCache.mReusableBitmaps.add(SoftReference(bitmapDrawable!!.bitmap))\r\n        }\r\n        val resId = resources[index]\r\n        decodeHandler!!.post {\r\n            val start = System.currentTimeMillis()\r\n            val resource = target!!.resources\r\n            bitmapDrawable = BitmapLoadUtils.decodeSampledBitmapFromRes(resource, resId, 0,\r\n                    0,\r\n                    imageCache, true)\r\n            val end = System.currentTimeMillis()\r\n            val decodeConsuming = end - start\r\n            val delay = duration - decodeConsuming\r\n            val actDelay = if (delay > 0) delay else 0\r\n            val finalDelay = if (isInitLoad) 0 else actDelay\r\n            isInitLoad = false\r\n            uiCallBack = Runnable {\r\n                ViewCompat.setBackground(target, bitmapDrawable)\r\n                index++\r\n                load()\r\n            }\r\n            uiHandler.postDelayed(uiCallBack, finalDelay)\r\n        }\r\n    }\r\n\r\n    inner class DecodeThread : HandlerThread(\"DecodeThread\")\r\n\r\n}\r\n```\r\n自动处理生命周期：\r\n```\r\ninterface IAutoDestroy {\r\n    fun autoDestroy()\r\n}\r\n\r\nclass LifeFragment : Fragment() {\r\n    private val set: MutableSet<IAutoDestroy> = mutableSetOf()\r\n\r\n    fun register(autoDestroy: IAutoDestroy) {\r\n        set.add(autoDestroy)\r\n    }\r\n\r\n    override fun onDestroy() {\r\n        super.onDestroy()\r\n        for (autoDestroy in set) {\r\n            autoDestroy.autoDestroy()\r\n        }\r\n    }\r\n}\r\n\r\nfun Context.registerAutoDestroy(autoDestroy: IAutoDestroy) {\r\n    if (this is FragmentActivity) {\r\n        var exist = supportFragmentManager.findFragmentByTag(\"Hello\")\r\n        if (exist == null) {\r\n            exist = LifeFragment()\r\n            supportFragmentManager.beginTransaction().add(exist, \"Hello\").commit()\r\n        }\r\n        if (exist is LifeFragment) {\r\n            exist.register(autoDestroy)\r\n        }\r\n    }else {\r\n        Log.e(\"registerAutoDestroy\", \"The context type do not support fragment\")\r\n    }\r\n}\r\n```"}}
{"actor":{"display_login":"nobeginning"}}