第十章 Service

295 阅读2分钟

第十章 Service

  1. 多线程

    1. Thread

      Thread {
      	// todo
      }.start()
      
      thread { 
        // todo 
      }
      
    2. Handler

      class ThreadActivity : BaseActivity() {
          val updateText = 1
          private lateinit var textView: TextView
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_thread)
              textView = findViewById(R.id.textView)
          }
      
          fun update(view: View) {
              thread {
                	// Message可以在内部携带少量信息,Int型的arg1和arg2,obj字段携带Object对象
                  val message = Message()
                  message.what = updateText
                  message.arg1
                  handler.sendMessage(message)
              }
          }
      
          val handler = object : Handler(Looper.getMainLooper()) {
              override fun handleMessage(msg: Message) {
                  super.handleMessage(msg)
                  when (msg.what) {
                      updateText -> {
                          textView.text = "123"
                      }
                  }
              }
          }
      }
      
    3. AsyncTask

      var myAsyncTask = object : AsyncTask<Void, Int, String>() {
          var count = 0
          override fun onPreExecute() {
              super.onPreExecute()
              textView.text = "准备阶段"
          }
      
          override fun doInBackground(vararg params: Void?): String {
              while (count <= 100) {
                  sleep(count.toLong())
                  publishProgress(count++)
              }
              return "执行完毕!"
          }
      
          override fun onPostExecute(result: String?) {
              super.onPostExecute(result)
              textView.text = result
          }
      
          override fun onProgressUpdate(vararg values: Int?) {
              super.onProgressUpdate(*values)
              textView.text = "当前进度 : ${values[0] ?: 0}%"
          }
      }
      
  2. Service

    1. startService()

      // startService()
      2021-07-11 20:34:14.855 6487-6487/com.youngly.firstlineofcode E/MyService: onCreate
      2021-07-11 20:34:14.860 6487-6487/com.youngly.firstlineofcode E/MyService: onStartCommand
      2021-07-11 20:34:14.860 6487-6487/com.youngly.firstlineofcode E/MyService: onStart
      // stopService()
      2021-07-11 20:34:15.962 6487-6487/com.youngly.firstlineofcode E/MyService: onDestroy
      

      缺点:启动后就失去了与service的联系

    2. bindService()

      class ServiceActivity : BaseActivity() {
          lateinit var downloadBinder: MyService.DownloadBinder
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_service)
          }
      
          fun start(view: View) {
              startService(Intent(this, MyService::class.java))
          }
      
          fun stop(view: View) {
              stopService(Intent(this, MyService::class.java))
          }
      
          val connection = object : ServiceConnection {
              override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                  downloadBinder = service as MyService.DownloadBinder
              }
      
              override fun onServiceDisconnected(name: ComponentName?) {
              }
      
          }
      
          fun bind(view: View) {
              bindService(Intent(this, MyService::class.java), connection, Context.BIND_AUTO_CREATE)
          }
      
          fun unbind(view: View) {
              unbindService(connection)
          }
      
          fun startDownload(view: View) {
              downloadBinder.startDownload()
          }
      
          fun getProgress(view: View) {
              downloadBinder.getProgress()
          }
      }
      
      class MyService : Service() {
      
      
          open class DownloadBinder : Binder() {
              fun startDownload() {
                  Log.e(TAG, "startDownload")
              }
      
              fun getProgress(): Int {
                  Log.e(TAG, "getProgress")
                  return 4
              }
          }
      
          private val downloadBinder = DownloadBinder()
      
          override fun onBind(intent: Intent): IBinder {
              return downloadBinder
          }
      
          override fun onCreate() {
              super.onCreate()
              Log.e(TAG, "onCreate")
          }
      
          override fun onStart(intent: Intent?, startId: Int) {
              super.onStart(intent, startId)
              Log.e(TAG, "onStart")
          }
      
          override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
              Log.e(TAG, "onStartCommand")
              return super.onStartCommand(intent, flags, startId)
          }
      
          override fun onUnbind(intent: Intent?): Boolean {
              return super.onUnbind(intent)
              Log.e(TAG, "onUnbind")
          }
      
          override fun onRebind(intent: Intent?) {
              super.onRebind(intent)
              Log.e(TAG, "onRebind")
          }
      
          override fun onDestroy() {
              super.onDestroy()
              Log.e(TAG, "onDestroy")
          }
      }
      
  3. 前台Service

    class ForegroundService : Service() {
    
        override fun onCreate() {
            super.onCreate()
            val notificationManager =
                getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                notificationManager.createNotificationChannel(
                    NotificationChannel(
                        "foregroundService",
                        "前台服务",
                        NotificationManager.IMPORTANCE_DEFAULT
                    )
                )
            }
            val build = NotificationCompat.Builder(this, "foregroundService")
                .setContentTitle("foreground Service title")
                .setContentText("service text")
                .setSmallIcon(R.drawable.ic_launcher_foreground)
                .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.apple_pic))
                .setContentIntent(
                    PendingIntent.getActivity(
                        this,
                        0,
                        Intent(this, MainActivity::class.java),
                        0
                    )
                )
                .build()
            startForeground(1, build)
        }
    
        override fun onBind(intent: Intent): IBinder {
            TODO("Return the communication channel to the service.")
        }
    }
    
    // 申请权限
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    
  4. IntentService

    private const val ACTION_FOO = "com.youngly.firstlineofcode.chapter10.action.FOO"
    private const val ACTION_BAZ = "com.youngly.firstlineofcode.chapter10.action.BAZ"
    
    private const val EXTRA_PARAM1 = "com.youngly.firstlineofcode.chapter10.extra.PARAM1"
    private const val EXTRA_PARAM2 = "com.youngly.firstlineofcode.chapter10.extra.PARAM2"
    
    class MyIntentService : IntentService("MyIntentService") {
    
        override fun onHandleIntent(intent: Intent?) {
            when (intent?.action) {
                ACTION_FOO -> {
                    val param1 = intent.getStringExtra(EXTRA_PARAM1)
                    val param2 = intent.getStringExtra(EXTRA_PARAM2)
                    handleActionFoo(param1, param2)
                }
                ACTION_BAZ -> {
                    val param1 = intent.getStringExtra(EXTRA_PARAM1)
                    val param2 = intent.getStringExtra(EXTRA_PARAM2)
                    handleActionBaz(param1, param2)
                }
            }
        }
    
        /**
         * Handle action Foo in the provided background thread with the provided
         * parameters.
         */
        private fun handleActionFoo(param1: String?, param2: String?) {
            TODO("Handle action Foo")
        }
    
        /**
         * Handle action Baz in the provided background thread with the provided
         * parameters.
         */
        private fun handleActionBaz(param1: String?, param2: String?) {
            TODO("Handle action Baz")
        }
    
        companion object {
            /**
             * Starts this service to perform action Foo with the given parameters. If
             * the service is already performing a task this action will be queued.
             *
             * @see IntentService
             */
            // TODO: Customize helper method
            @JvmStatic
            fun startActionFoo(context: Context, param1: String, param2: String) {
                val intent = Intent(context, MyIntentService::class.java).apply {
                    action = ACTION_FOO
                    putExtra(EXTRA_PARAM1, param1)
                    putExtra(EXTRA_PARAM2, param2)
                }
                context.startService(intent)
            }
    
            /**
             * Starts this service to perform action Baz with the given parameters. If
             * the service is already performing a task this action will be queued.
             *
             * @see IntentService
             */
            // TODO: Customize helper method
            @JvmStatic
            fun startActionBaz(context: Context, param1: String, param2: String) {
                val intent = Intent(context, MyIntentService::class.java).apply {
                    action = ACTION_BAZ
                    putExtra(EXTRA_PARAM1, param1)
                    putExtra(EXTRA_PARAM2, param2)
                }
                context.startService(intent)
            }
        }
    }
    
    MyIntentService.startActionBaz(this, "", "")
    
  5. Kotlin课堂

    1. 泛型实例化

      Java泛型功能是通过类型擦除机制实现的。

      泛型对于类型的约束只在编译期,运行的时候JVM识别不出我们在代码中指定的泛型类型。

      泛型实例化:该函数必须是内联函数,声明泛型的地方必须加上reified关键字。

      inline fun <reified T> getGenericType() = T::class.java
      

      可以获取到泛系实际类型的功能

      泛型实例化应用:

      inline fun <reified T> Activity.start() {
          startActivity(Intent(this, T::class.java))
      }
      
      // 无参
      start<ServiceActivity>()
      
      inline fun <reified T> Activity.start(block: Intent.() -> Unit) {
          val intent = Intent(this, T::class.java)
          intent.block()
          startActivity(intent)
      }
      
      // 有参
      start<ServiceActivity> {
                  putExtra("type", "")
              }
      
    2. 协变

    3. 逆变

    4. @UnsafeVariance