项目作者: runningmessage

项目描述 :
To use kotlin easily !!!
高级语言: Kotlin
项目地址: git://github.com/runningmessage/kotlinx-android.git
创建时间: 2019-12-04T03:29:05Z
项目社区:https://github.com/runningmessage/kotlinx-android

开源协议:

下载


kotlinx-android

How to use


maven

  1. <dependency>
  2. <groupId>com.runningmessage.kotlinx-android</groupId>
  3. <artifactId>kotlinx-reflect</artifactId>
  4. <version>0.0.7</version>
  5. <type>pom</type>
  6. </dependency>
  7. <dependency>
  8. <groupId>com.runningmessage.kotlinx-android</groupId>
  9. <artifactId>kotlinx-common</artifactId>
  10. <version>0.0.7</version>
  11. <type>pom</type>
  12. </dependency>
  13. <dependency>
  14. <groupId>com.runningmessage.kotlinx-android</groupId>
  15. <artifactId>kotlinx-widget</artifactId>
  16. <version>0.0.7</version>
  17. <type>pom</type>
  18. </dependency>

gradle

  1. //project build.gradle
  2. buildscript {
  3. repositories {
  4. ...
  5. //add the maven url
  6. maven { url "https://dl.bintray.com/runningmessage/maven" }
  7. }
  8. }
  9. //app build.gradle
  10. compile 'com.runningmessage.kotlinx-android:kotlinx-reflect:0.0.7'
  11. compile 'com.runningmessage.kotlinx-android:kotlinx-common:0.0.7'
  12. compile 'com.runningmessage.kotlinx-android:kotlinx-widget:0.0.7'

ivy

  1. <dependency org="com.runningmessage.kotlinx-android" name="kotlinx-reflect" rev="0.0.7">
  2. <artifact name="kotlinx-common" ext="pom"></artifact>
  3. </dependency>
  4. <dependency org="com.runningmessage.kotlinx-android" name="kotlinx-common" rev="0.0.7">
  5. <artifact name="kotlinx-common" ext="pom"></artifact>
  6. </dependency>
  7. <dependency org="com.runningmessage.kotlinx-android" name="kotlinx-widget" rev="0.0.7">
  8. <artifact name="kotlinx-widget" ext="pom"></artifact>
  9. </dependency>

kotlinx-reflect

Some functions to make reflective calls.

simple example

Demo.01 simple example

  1. import com.runningmessage.kotlinx.reflect.*
  2. lateinit var context: Context
  3. val Builder = "android.support.v7.app.AlertDialog${'$'}Builder"
  4. val OnClickListener = "android.content.DialogInterface${'$'}OnClickListener"
  5. Builder(context) // Like AlertDialog.Builder(context)
  6. .calls("setTitle")("Hello World") // Call matched specific named function
  7. .calls("setPositiveButton")("OK",
  8. OnClickListener.createInners{ // Like object: DialogInterface.OnClickListener
  9. /***
  10. * Like:
  11. * override fun onClick(dialog: Any, which: Int){
  12. *
  13. * }
  14. */
  15. override<Any, Int>("onClick"){ dialog, which ->
  16. }
  17. })
  18. .calls("create").calls("show")() // Like builder.create().show()

Demo.02 Call function by reflect

  1. private lateinit var activity: Any
  2. activity.runInActivity()
  3. private fun Any.runInActivity() {// In the code below , [this] is Activity Object
  4. /***
  5. * setContentView(R.layout.activity_main)
  6. * ***/
  7. calls("setContentView")(R.layout.activity_main)
  8. /***
  9. * val npRecyclerView = findViewById<ViewGroup>(R.id.npRecyclerView)
  10. * ***/
  11. val npRecyclerView = call<ViewGroup>("findViewById")(R.id.npRecyclerView)
  12. val makeText = "android.widget.Toast.makeText"
  13. callsStatic(makeText)(applicationContext, "Hello World", 0)
  14. .calls("show")()
  15. ... ...
  16. }

Demo.03 Create instance by reflect

  1. /***************************** Import to reflect *****************************/
  2. /** The string below can be used just same as declared class in the code **/
  3. private const val MyLoadMoreRecyclerAdapter = "com.runningmessage.kotlinx.demo.MyLoadMoreRecyclerAdapter"
  4. private const val StaggeredGridLayoutManager = "android.support.v7.widget.StaggeredGridLayoutManager"
  5. private fun Any.runInActivity() {// In the code below , [this] is Activity Object
  6. ... ..
  7. // set the load more recycler adapter
  8. val applicationContext = call<Context>("getApplicationContext")()
  9. /***
  10. * the declared string [MyLoadMoreRecyclerAdapter] can be used same as class which is imported
  11. *
  12. * val adapter = com.runningmessage.kotlinx.demo.MyLoadMoreRecyclerAdapter(applicationContext)
  13. * ***/
  14. val adapter: Any? = MyLoadMoreRecyclerAdapter(applicationContext)
  15. /***
  16. * the declared string [StaggeredGridLayoutManager] can be used same as class which is imported
  17. *
  18. * npRecyclerView.setLayoutManager(StaggeredGridLayoutManager(2, 1))
  19. * ***/
  20. npRecyclerView.calls("setLayoutManager")(StaggeredGridLayoutManager(2, 1))
  21. ... ...
  22. }

Demo.04 Call property by reflect

  1. private fun Any.runInActivity() {// In the code below , [this] is Activity Object
  2. ... ..
  3. /***
  4. * adapter.isAutoLoadMore = false
  5. ***/
  6. adapter.propertys("isAutoLoadMore").value = false
  7. /***
  8. * val count = adapter.dataCount
  9. ***/
  10. val count = adapter.property<Int>("dataCount").value ?: 0
  11. val makeText = "android.widget.Toast.makeText"
  12. val LENGTH_LONG = "android.widget.Toast.LENGTH_LONG"
  13. callsStatic(makeText)(applicationContext, "Hello World", propertyStatic<Int>(LENGTH_LONG).value ?: 0)
  14. .calls("show")()
  15. ... ...
  16. }

Demo.05 Create anonymous inner class instance by reflect

  1. val TextWatcher = "android.text.TextWatcher"
  2. val watcher = TextWatcher.createInners{ // Like val watcher = object: TextWatcher{ ... ... }
  3. /**
  4. * override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
  5. *
  6. * }
  7. **/
  8. override<CharSequence, Int, Int, Int>("beforeTextChanged"){
  9. s, start, before, count ->
  10. }
  11. /**
  12. * override fun onTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
  13. *
  14. * }
  15. **/
  16. override("onTextChanged"){
  17. s: CharSequence?, start: Int?, before: Int?, count: Int? ->
  18. }
  19. /**
  20. * override fun afterTextChanged(s: Editable?) {
  21. *
  22. * }
  23. **/
  24. override("afterTextChanged", CallHandlerFunction { args: Array<out Any?>? ->
  25. val s = args?.get(0) as? Editable
  26. })
  27. }

Demo.06 Call instanceOf/is by reflect

  1. val AppCompatActivity = "android.support.v7.app.AppCompatActivity"
  2. lateinit var activity: Any
  3. if(activity iss AppCompatActivity){
  4. // do something
  5. }
  6. activity.ifIs(AppCompatActivity) { appCompatActivity: Any ->
  7. appCompatActivity.runInActivity()
  8. }
  9. // another sample
  10. val context: Context? = activity.ifIs(AppCompatActivity) { appCompatActivity: Any ->
  11. return@ifIs appCompatActivity.call<Context>("getApplicationContext")()
  12. }

kotlinx-widget

AbsSwipeRefreshLayout:

  1. rewite SwipeRefreshLayout :
  2. 1. support pull down to refresh and enable to custom pull refresh anim: 支持下拉刷新自定义刷新动画
  3. 2. support show remind pop view after pull refresh: 支持刷新完成后弹窗提醒

LoadMoreRecyclerAdapter:

  1. custom RecyclerView.Adapter :
  2. 1. support pull up load more: 支持上拉加载更多

kotlinx-common

ActivityExt:

  1. Activity.contentView
  2. 1. return the content view set by [Activity.setContentView]
  1. Activity.startActivityForResult<MyActivity>(requestCode, bundle)
  2. // same with below
  3. Activity.startActivityForResult(Intent(context, MyActivity::class.java), requestCode, bundle)
  1. Activity.startActivityForResult<MyActivity>(requestCode, bundle){
  2. action = "com.action.xxx"
  3. putExtra("key", "value")
  4. }
  5. // same with below
  6. val intent = Intent(context, MyActivity::class.java).apply{
  7. action = "com.action.xxx"
  8. putExtra("key", "value")
  9. }
  10. Activity.startActivityForResult(intent, requestCode, bundle)
  1. Activity.startActivityForResult("com.action.xxx", requestCode, bundle){
  2. putExtra("key", "value")
  3. }
  4. // same with below
  5. val intent = Intent("com.action.xxx").apply{
  6. putExtra("key", "value")
  7. }
  8. Activity.startActivityForResult(intent, requestCode, bundle)

AndroidExt:

  1. /** Do something depending on android sdk, for <b>compatibility</b> */
  2. /** 判断安卓SDK版本后 执行代码, <b>兼容性</b> */
  3. ifSdk(16, 19, 29) {
  4. //do something if Build.VERSION.SDK_INT is one of 16, 19, 29
  5. } other {
  6. //otherwise, do other thing
  7. }
  8. ifNotSdk(16, 19, 29) {
  9. //do something if Build.VERSION.SDK_INT is not 16, 19 or 29
  10. } other {
  11. //otherwise, do other thing
  12. }
  13. fromSdk(16) {
  14. //do something if Build.VERSION.SDK_INT >= 16
  15. } other {
  16. //otherwise, Build.VERSION.SDK_INT < 16, do other thing
  17. }
  18. toSdk(16) {
  19. //do something if Build.VERSION.SDK_INT <= 16
  20. } other {
  21. //otherwise, Build.VERSION.SDK_INT > 16, do other thing
  22. }
  23. afterSdk(16) {
  24. //do something if Build.VERSION.SDK_INT > 16
  25. } other {
  26. //otherwise, Build.VERSION.SDK_INT <= 16, do other thing
  27. }
  28. untilSdk(16) {
  29. //do something if Build.VERSION.SDK_INT < 16
  30. } other {
  31. //otherwise, Build.VERSION.SDK_INT >= 16, do other thing
  32. }

AnyExt.kt

  1. Any.ifNull{
  2. // do something and return the default vale when null
  3. }

BitmapExt:

  1. Bitmap?.createRoundedCornerBitmap
  2. 1. create a new rounded corner bitmap, basing on the current bitmap: 基于当前 Bitmap 创建一个带圆角的 Bitmap

ContextExt:

  1. Context?.toastShort(msg)
  2. Context?.toastShort(resId)
  3. Context?.toastLong(msg)
  4. Context?.toastLong(resId)
  5. Context.dpToPx(dp)
  6. 1. cast the [dp] dip into px unit
  7. Context.pxToDp(px)
  8. 1. cast the [px] px into dip unit
  9. Context.screenWidth()
  10. 1. get the screen width pixels ,
  11. same as [Context.getResources].[getDisplayMetrics].[widthPixels]
  12. Context.screenWidthShort()
  13. 1. return the smaller between [screenWidth] and [screenHeight]
  14. Context.screenWidthX()
  15. 1. return the [screenWidthShort] if current is orientation portrait, otherwise the [screenHeightLong]
  16. Context.screenHeight()
  17. 1. get the screen height pixels ,
  18. same as [Context.getResources].[getDisplayMetrics].[heightPixels]
  19. Context.screenHeightLong()
  20. 1. return the larger between [screenWidth] and [screenHeight]
  21. Context.screenHeightY()
  22. 1. return the [screenHeightLong] if current is orientation portrait, otherwise the [screenWidthShort]
  1. Context.startActivity<MyActivity>()
  2. // same with below
  3. Context.startActivity(Intent(context, MyActivity::class.java))
  1. Context.startActivity<MyActivity>{
  2. action = "com.action.xxx"
  3. putExtra("key", "value")
  4. }
  5. // same with below
  6. val intent = Intent(context, MyActivity::class.java).apply{
  7. action = "com.action.xxx"
  8. putExtra("key", "value")
  9. }
  10. Context.startActivity(intent)
  1. context.startActivity("com.action.xxx"){
  2. putExtra("key", "value")
  3. }
  4. // same with below
  5. val intent = Intent("com.action.xxx").apply{
  6. putExtra("key", "value")
  7. }
  8. context.startActivity(intent)

HandlerExt:

  1. Handler.postDelayed(delay){
  2. // do something
  3. }

NoLeakListenerFunction1:

  1. wrap the Listener implementing interface , which only has one callback method, **Avoid Memory Leak !!!**
  2. 包装 只实现 有一个单独方法的接口 的监听器, 并返回代理对象, ***避免内存泄漏 !!!***

StringExt.kt

  1. CharSequence.ifNullOrEmpty{}
  2. CharSequence.ifNullOrBlank{}
  3. CharSequence.ifNotNullOrEmpty{}
  4. CharSequence.ifNotNullOrBlank{}

SupportExt.kt

  1. FragmentClassSupport
  2. FragmentGetActivitySupport
  3. FragmentIsRemovingSupport

TextViewExt:

  1. TextView.addEllipsis:
  2. 1. add "…" after the end of text: TextView 显示的文本末尾添加省略号( )

ThreadExt:

  1. object UiThreadHandler
  2. 1. The UI thread handler
  3. isMainThread()
  4. 1. return whether the current thread is main thread
  1. /***
  2. * create a new [Thread] and start to run the [block]
  3. */
  4. runOnNewThread {
  5. // do something in a new thread
  6. }
  7. // same with below
  8. Thread{
  9. // do something in a new thread
  10. }.start()
  1. /***
  2. * create a new [HandlerThread] named "HandlerThread-[nextThreadNum]",
  3. * and send message to the [Handler] associated with this [HandlerThread].[getLooper()][HandlerThread.getLooper] to run the [block] after [delay] milliseconds,
  4. * and then to call [HandlerThread.quitSafely] or [HandlerThread.quit] after [block] invoke
  5. */
  6. postOnNewThread(1000) {
  7. // do something in a new thread after 1000 milliseconds
  8. }
  9. // same with below
  10. val handler = Handler(HandlerThread("HandlerThread-${nextThreadNum()}").apply { start() }.looper)
  11. handler.postDelayed(1000) {
  12. try {
  13. // do something in a new thread after 1000 milliseconds
  14. } finally {
  15. (Thread.currentThread() as? HandlerThread)?.let { thread ->
  16. fromSdk(18) {
  17. thread.quitSafely()
  18. } other {
  19. thread.quit()
  20. }
  21. }
  22. }
  23. }
  1. /***
  2. * if no [Looper] has associated with [currentThread][Thread.currentThread], just to [prepare][Looper.prepare] and call [Looper.loop],
  3. * in this case, it will call [HandlerThread.quitSafely] or [HandlerThread.quit] after [block] invoke;
  4. * and then send message to the [Handler] associated with [currentThread][Thread.currentThread].[looper][Looper.myLooper] to run the [block] after [delay] milliseconds
  5. */
  6. postOnCurrentThread(1000) {
  7. // do something in current thread after 1000 milliseconds
  8. }
  9. // same with below
  10. if (isMainThread()) {
  11. postOnUiThread(1000){
  12. // do something in current thread after 1000 milliseconds
  13. }
  14. } else {
  15. var needQuitLooper = false
  16. val looper: Looper? = Looper.myLooper().ifNull {
  17. needQuitLooper = true
  18. Looper.prepare()
  19. Looper.myLooper()
  20. }
  21. postOnUiThread {
  22. Handler(looper).postDelayed(1000) {
  23. try {
  24. // do something in current thread after 1000 milliseconds
  25. } finally {
  26. if (needQuitLooper) {
  27. fromSdk(18) {
  28. looper?.quitSafely()
  29. } other {
  30. looper?.quit()
  31. }
  32. }
  33. }
  34. }
  35. }
  36. Looper.loop()
  37. }
  1. runOnUiThread(target) {
  2. // do something in ui thread,
  3. // and try to associate with the lifecycle for target , when target is not null
  4. }
  5. postOnUiThread(target, 1000){
  6. // do something in ui thread after 1000 milliseconds,
  7. // and try to associate with the lifecycle for target , when target is not null
  8. }
  1. Runnable.runOnUiThread(target)
  2. 1. immediately run the task, if current is on UI thread
  3. 2. otherwise, to post the task into run queue, or maybe a ui thread handler
  4. Runnable.postOnUiThread(target, delay)
  5. 1. post the task into run queue, or maybe a ui thread handler;
  6. and the task will be to run after [delay] milliseconds ,
  7. even if the [delay] is less than 0, it is still waiting the run queue to call running

ViewExt:

  1. View.setVisible() // visibility = View.VISIBLE
  2. View.isVisible() // return visibility == View.VISIBLE
  3. View.setInvisible() // visibility = View.INVISIBLE
  4. View.isInvisible() // return visibility == View.INVISIBLE
  5. View.setGone() // visibility = View.GONE
  6. View.isGone() // return visibility = View.GONE
  1. View.layoutLeftMargin:
  2. 1. return the leftMargin of the layoutParams for the current View, if exists , otherwise return null
  3. 2. set the leftMargin of the layoutParams for the current View, and reset the layoutParams
  4. View.layoutRightMargin:
  5. 1. return the rightMargin of the layoutParams for the current View, if exists , otherwise return null
  6. 2. set the rightMargin of the layoutParams for the current View, and reset the layoutParams
  7. View.layoutTopMargin:
  8. 1. return the topMargin of the layoutParams for the current View, if exists , otherwise return null
  9. 2. set the topMargin of the layoutParams for the current View, and reset the layoutParams
  10. View.layoutBottomMargin:
  11. 1. return the bottomMargin of the layoutParams for the current View, if exists , otherwise return null
  12. 2. set the bottomMargin of the layoutParams for the current View, and reset the layoutParams
  13. View.layoutWidth:
  14. 1. return the width of the layoutParams for the current View, if exists , otherwise return null
  15. 2. set the width of the layoutParams for the current View, and reset the layoutParams
  16. View.layoutHeight:
  17. 1. return the height of the layoutParams for the current View, if exists , otherwise return null
  18. 2. set the height of the layoutParams for the current View, and reset the layoutParams
  1. View.postDelayed(delay){
  2. // do something
  3. }

ViewGroupExt:

  1. ViewGroup.views
  2. 1. the list of child view
  3. ViewGroup.firstView
  4. 1. the first child view
  5. ViewGroup.lastView
  6. 1. the last child view